문자열 비교시 Sqlite3를 대소 문자를 구분하지 않도록 설정하는 방법은 무엇입니까?


305

문자열 일치로 sqlite3 데이터베이스에서 레코드를 선택하고 싶습니다. 그러나 where 절에서 '='를 사용하면 sqlite3이 대소 문자를 구분한다는 것을 알았습니다. 누구든지 대소 문자를 구분하지 않고 문자열을 사용하는 방법을 말해 줄 수 있습니까?

답변:


493

쿼리 COLLATE NOCASE에서 사용할 수 있습니다 SELECT.

SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE

또한 SQLite에서는 collate nocase열 정의에서 지정하여 테이블을 만들 때 열이 대소 문자를 구분하지 않음을 나타낼 수 있습니다 (다른 옵션은 binary(기본값) 및rtrim ; 여기 참조 ). collate nocase인덱스를 만들 때도 지정할 수 있습니다 . 예를 들면 다음과 같습니다.

테이블 테스트 작성
(
  Text_Value 텍스트는 nocase를 조합합니다.
);

시험 값에 삽입 ( 'A');
시험 값에 삽입 ( 'b');
시험 값에 삽입 ( 'C');

인덱스 생성 Test_Text_Value_Index
  테스트 중 (Text_Value collate nocase);

관련된 표현식 Test.Text_Value은 이제 대소 문자를 구분하지 않아야합니다. 예를 들면 다음과 같습니다.

sqlite> 테스트에서 Text_Value를 선택하십시오. 여기서 Text_Value = 'B';
Text_Value      
----------------
비               

sqlite> Text_Value로 테스트 순서에서 Text_Value를 선택하십시오.
Text_Value      
----------------
ㅏ               
비               
씨    

sqlite> Text_Value desc로 테스트 순서에서 Text_Value를 선택하십시오.
Text_Value      
----------------
씨               
비               
ㅏ               

옵티마이 저는 또한 컬럼에서 대소 문자를 구분하지 않는 검색 및 일치를 위해 인덱스를 사용할 수 있습니다. 다음 explain과 같은 SQL 명령을 사용하여이를 확인할 수 있습니다 .

sqlite> 설명 Text_Value = 'b'테스트에서 select Text_Value를 설명하십시오.
가산기 opcode p1 p2 p3                               
---------------- -------------- ---------- ------------ ---------------------------------
0 고토 0 16                                           
1 정수 0 0                                            
2 OpenRead 1 3 키 정보 (1, NOCASE)                
3 열 숫자 열 1 2                                            
문자열 4 0 0 b                                
5 IsNull -1 14                                           
6 MakeRecord 1 0 a                                
7 MemStore 0 0                                            
8 이동 1 1 14                                           
9 MemLoad 0 0                                            
10 IdxGE 1 14 +                                
11 열 1 0                                            
콜백 1 0                                            
13 다음 1 9                                            
14 닫기 1 0                                            
15 정지 0 0                                            
16 거래 0 0                                            
17 VerifyCookie 0 4                                            
18 고토 0 1                                            
19 op 0 0                                            

20
'COLLATE NOCASE'를 사용하여 테이블을 만든 후 쿼리 이름 = '누군가'COLLATE NOCASE보다 훨씬 빠릅니다. 훨씬 빠르다 (6 ~ 10 배, 대략?)
DefenestrationDay

10
문서에 따르면 COLLATE NOCASE필드 자체에이 데이터 정렬이 이미 정의되어 있으면 색인에 추가 할 필요가 없습니다. " 기본 데이터 정렬 시퀀스는 CREATE TABLE 문에서 해당 열에 대해 정의 된 데이터 정렬 시퀀스입니다. "
Heinzi

29
COLLATE NOCASEASCII 텍스트에서만 작동합니다. 열 값에 "FIANCÉ"또는 "voilà"가 있으면 "fiancé"또는 "VOILA"와 일치하지 않습니다. ICU 확장을 활성화 한 후 LIKE대소 문자를 구분하지 않으므로 'FIANCÉ' LIKE 'fiancé'true이지만 'VOILA' LIKE 'voilà'여전히 false입니다. 그리고 ICU + LIKE는 인덱스를 사용하지 않으면 단점이 있으므로 큰 테이블에서는 느려질 수 있습니다.

div를 선택하십시오. div = 'fail'인 경우 'FAIL', 그렇지 않은 경우 'PASSED'끝, * 위의 마크 소트에서 작동하지 않습니다.
Thunder

7
한 가지주의 할 점은 다음과 같습니다. select * from tbl where firstname='john' and lastname='doe' COLLATE NOCASE는 대소 문자를 구분하지 않습니다 lastname. 에 대소 문자를 구분하지 않으려면 다음 firstname과 같이 작성하십시오 select * from tbl where firstname='john' COLLATE NOCASE and lastname='doe'. 전체 where절이 아니라 하나의 열에 만 적용됩니다 .
James Toomey

148
SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE

5
나와 같은데 Collating에 대한 추가 문서를 원하면이 페이지에서 찾을 수 있습니다. sqlite.org/datatype3.html 그냥 아래로 스크롤 하십시오 # 6.0
Will

47

다음과 같이 할 수 있습니다 :

SELECT * FROM ... WHERE name LIKE 'someone'

(그것은 아니다 솔루션,하지만 어떤 경우에는 매우 편리합니다)

" LIKE 연산자는 패턴 일치 비교를 수행합니다. 오른쪽의 피연산자는 패턴을 포함하고 왼쪽 피연산자는 패턴과 일치하는 문자열을 포함합니다. 패턴의 백분율 기호 ("% ")는 0 이상의 시퀀스와 일치합니다. 문자열의 문자 패턴의 밑줄 ( "_")은 문자열의 단일 문자와 일치 하고 다른 문자는 자체 또는 대소 문자를 구분합니다 (예 : 대소 문자를 구분하지 않음 ) (버그 : SQLite 만 이해 ASCII 문자의 경우 대문자 / 소문자 LIKE 연산자는 ASCII 범위를 벗어난 유니 코드 문자의 경우 대소 문자를 구분합니다 (예 : 'a'LIKE 'A'는 TRUE이지만 'æ'LIKE 'Æ'"FALSE입니다.")


@ MM-BB 그렇습니다. COLLATE NOCASE로 선언 된 (또는 색인화 된) 열에서 LIKE를 수행하지 않으면 행 전체를 스캔합니다.
Nick Dandoulakis

1
버그가 아니며 문서화 된 제한 사항입니다. 답변에 인용 된 동일한 페이지에는 유니 코드 문자를 관리하는 ICU 확장이 언급되어 있습니다. (아마 2009 년이 아닐 수도 있습니다)
stenci

40

이것은 sqlite에만 국한되지는 않지만 할 수 있습니다.

SELECT * FROM ... WHERE UPPER(name) = UPPER('someone')

성능 문제의 다른 부분은 테이블에서 일치하는 행을 찾는 것입니다. SQLite3는 함수 기반 인덱스를 지원합니까? 이와 같은 상황에서 검색 열 또는 표현식 (예 : "UPPER (name)")을 인덱싱하는 것이 좋습니다.
cheduardo 2016 년

13
cheduardo가 암시했듯이 SQLite는이 쿼리를 실행할 때 'name'에서 인덱스를 사용할 수 없습니다. db 엔진은 모든 'name'필드를 대문자로 변환하고 비교를 실행하여 모든 행을 전체 스캔해야합니다.
Mathew Waters

1
@ 수량, 예, 많이.
베르가

4

다른 옵션은 사용자 정의 데이터 정렬을 만드는 것입니다. 그런 다음 열에서 해당 데이터 정렬을 설정하거나 select 절에 추가 할 수 있습니다. 주문 및 비교에 사용됩니다.

이것은 'voilà'처럼 'VOILA'를 만드는 데 사용될 수 있습니다.

http://www.sqlite.org/capi3ref.html#sqlite3_create_collation

배열 함수는 첫 번째 문자열이 각각 두 번째보다 작거나 같거나 큰 경우 음수, 0 또는 양의 정수를 반환해야합니다.


2

귀하의 경우에는 이해가되지 않을 수도있는 또 다른 옵션은 실제로 기존 열의 사전 점수가 낮은 별도의 열을 갖는 것입니다. 이것은 SQLite 함수를 사용하여 채울 수 있습니다LOWER() 대신이 열에서 일치를 수행 할 수 있습니다.

분명히 중복성과 불일치 가능성이 추가되지만 데이터가 정적 인 경우 적합한 옵션 일 수 있습니다.


2

간단히 SELECT 쿼리에서 COLLATE NOCASE를 사용할 수 있습니다.

SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE

1

열이 유형 인 경우 char공백으로 쿼리하는 값을 추가해야합니다 . 여기 에서이 질문을 참조 하십시오 . 이것은 COLLATE NOCASE또는 다른 솔루션 중 하나 를 사용하는 것 외에도 (upper () 등).



0

그것은 나를 위해 완벽하게 작동합니다. SELECT NAME FROM TABLE_NAME WHERE NAME = 'test Name' COLLATE NOCASE

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.