文字列比較時に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 collat​​e nocase);

関係Test.Text_Valueする式では、大文字と小文字が区別されなくなりました。例えば:

sqlite> Text_Value = 'B'のテストからText_Valueを選択します。
Text_Value      
----------------
b               

sqlite> Text_ValueによるテストオーダーからText_Valueを選択します。
Text_Value      
----------------
あ               
b               
C    

sqlite> Text_Valueによるテストの順序からText_Valueを選択しますdesc;
Text_Value      
----------------
C               
b               
あ               

オプティマイザは、大文字と小文字を区別しない検索と列の照合にインデックスを利用する可能性もあります。これは、explainSQLコマンドを使用して確認できます。例:

sqlite> ExplainからText_Value = 'b'を選択して、Text_Valueを選択します。
addrオペコードp1 p2 p3                               
---------------- -------------- ---------- ---------- ---------------------------------
0後藤0 16                                           
1整数0 0                                            
2 OpenRead 1 3 keyinfo(1、NOCASE)                
3 SetNumColumns 1 2                                            
4文字列8 0 0 b                                
5 IsNull -1 14                                           
6 MakeRecord 1 0 a                                
7 MemStore 0 0                                            
8 MoveGe 1 14                                           
9 MemLoad 0 0                                            
10 IdxGE 1 14 +                                
11列1 0                                            
12コールバック1 0                                            
13次へ1 9                                            
14クローズ1 0                                            
15停止0 0                                            
16トランザクション0 0                                            
17 VerifyCookie 0 4                                            
18後藤0 1                                            
19なし0 0                                            

20
'COLLATE NOCASE'を使用してテーブルを(再)作成した後、クエリWHERE name = 'someone' COLLATE NOCASEよりもはるかに高速であることに気付きました。はるかに高速(
6〜10

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にはインデックスを使用しないという欠点があるため、大きなテーブルでは遅くなる可能性があります。

select div、case when div = 'fail' then 'FAIL' else 'PASSED' end、* from mark collat​​e nocase does not work not work私は何か間違っていますか?
サンダー

7
気が付いたことの1つ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句全体ではなく、その1つの列に固有です。
James Toomey 2017

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

5
あなたは私のようなものと照合の詳細ドキュメントをしたい場合は、このページにそれをここに見つけることができます:sqlite.org/datatype3.html ただ、#6.0までスクロール
ウィル

47

あなたはこのようにそれを行うことができます:

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

(それ解決策ではありませんが、場合によっては非常に便利です)

" LIKE演算子はパターンマッチングの比較を行います。右側のオペランドにはパターンが含まれ、左側のオペランドにはパターンと照合する文字列が含まれます。パターン内のパーセント記号("% ")は0以上のシーケンスと一致します文字列内の文字。パターン内の下線( "_")は、文字列内の任意の1文字と一致します。他の文字は、 それ自体またはその大文字/ 小文字に 一致します(つまり、大文字と小文字を区別しない一致)。(バグ:SQLiteは、 ASCII文字の大文字/小文字。LIKE演算子は、ASCIIの範囲を超えるUnicode文字の大文字と小文字を区別します。たとえば、式 'a' LIKE 'A'はTRUEですが、 'æ' LIKE 'Æ'はFALSEです。」


@ MM-BBはい、COLLATE NOCASEとして宣言(またはインデックス付け)された列でLIKEを実行しない限り、行のフルスキャンが実行されます。
Nick Dandoulakis 14

1
これはバグではなく、文書化された制限です。回答で引用されている同じページは、ユニコード文字を管理するICU拡張機能について言及しています。(おそらく2009年ではそうではなかった)
stenci

40

これはsqliteに固有のものではありませんが、あなたはただ行うことができます

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

パフォーマンスに関するもう1つの問題は、テーブルで一致する行を見つけることです。SQLite3は関数ベースのインデックスをサポートしていますか?このような状況で検索列または式(たとえば、 "UPPER(name)")にインデックスを付けることは、通常は良い考えです。
cheduardo 2009年

13
cheduardoがほのめかしたように、SQLiteはこのクエリを実行するときに 'name'のインデックスを利用できません。dbエンジンはすべての行をフルスキャンして、すべての「name」フィールドを大文字に変換して比較を実行する必要があります。
マシューウォーターズ

1
@数量、はい、たくさん。
ベルガ

4

別のオプションは、独自のカスタム照合を作成することです。次に、その照合を列に設定するか、選択句に追加できます。順序付けと比較に使用されます。

これは、「VOILA」を「voilà」のように作成するために使用できます。

http://www.sqlite.org/capi3ref.html#sqlite3_create_collat​​ion

照合関数は、最初の文字列が2番目の文字列より小さい、等しい、または大きい場合、それぞれ負、ゼロ、または正の整数を返す必要があります。


2

あなたの場合に意味があるかもしれないし、意味がないかもしれない別のオプションは、実際に既存の列の事前にスコアが付けられた値を持つ別の列を持つことです。これは、SQLite関数を使用して入力できますLOWER()でき、代わりにこの列でマッチングを実行できます。

明らかに、それは冗長性と不整合の可能性を追加しますが、データが静的である場合、それは適切なオプションかもしれません。


2

簡単に言うと、SELECTクエリでCOLLATE NOCASEを使用できます。

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

1

列がタイプの場合、charクエリする値にスペースを追加する必要があります。この質問をここで参照してください。これに加えて、COLLATE NOCASEまたは他のソリューション(upper()など)の1つを使用します。



0

それは私のために完全に働いています。 SELECT NAME FROM TABLE_NAME WHERE NAME = 'test Name' COLLATE NOCASE

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.