Dize karşılaştırması sırasında Sqlite3'ün büyük / küçük harfe duyarlı olmaması nasıl ayarlanır?


305

Dize eşleşmesi ile sqlite3 veritabanından kayıtları seçmek istiyorum. Ama nerede yan tümcesinde '=' kullanırsam, sqlite3'ün büyük / küçük harfe duyarlı olduğunu fark ettim. Herkes büyük / küçük harfe duyarlı olmayan dize nasıl kullanacağımı söyleyebilir mi?

Yanıtlar:


493

Sen kullanabilirsiniz COLLATE NOCASEsizin de SELECTsorguda:

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

Ayrıca, SQLite'de, collate nocasesütun tanımında (diğer seçenekler binary(varsayılan) ve burayartrim bakın ) tabloyu oluştururken bir sütunun büyük / küçük harfe duyarlı olmaması gerektiğini belirtebilirsiniz . Ne zaman bir dizin oluşturacağınızı da belirtebilirsiniz . Örneğin:collate nocase

tablo oluştur Test
(
  Text_Value metin harmanlama nocase
);

Test değerlerine girin ('A');
Test değerlerine girin ('b');
Test değerlerine girin ('C');

dizin oluştur Test_Text_Value_Index
  Testte (Text_Value collate nocase);

İlgili ifadeler Test.Text_Valueartık büyük / küçük harfe duyarsız olmalıdır. Örneğin:

sqlite> Test'ten Text_Value'yu seçin; burada Text_Value = 'B';
TEXT_VALUE      
----------------
b               

sqlite> Text_Value tarafından Test siparişinden Text_Value seçin;
TEXT_VALUE      
----------------
bir               
b               
C    

sqlite> Text_Value tarafından Test sırasından Text_Value seçin;
TEXT_VALUE      
----------------
C               
b               
bir               

Optimize edici ayrıca büyük olasılıkla büyük / küçük harfe duyarlı olmayan arama ve eşleme için dizinden yararlanabilir. Bunu explainSQL komutunu kullanarak kontrol edebilirsiniz , örneğin:

sqlite> açıklamak Test'ten Text_Value'yu seçin; burada Text_Value = 'b';
addr opcode p1 p2 p3                               
---------------- -------------- ---------- ---------- ---------------------------------
0 Git 0 16                                           
1 Tamsayı 0 0                                            
2 OpenRead 1 3 keyinfo (1, NOCASE)                
3 SetNumColumns 1 2                                            
4 Tel 8 0 0 b                                
5 IsNull -1 14                                           
6 Marka Kaydı 1 0 a                                
7 MemStore 0 0                                            
8 MoveGe 1 14                                           
9 MemLoad 0 0                                            
10 IdxGE 1 14 +                                
11 Sütun 1 0                                            
12 Geri Arama 1 0                                            
13 Sonraki 1 9                                            
14 Kapat 1 0                                            
15 Durdur 0 0                                            
15 İşlem 0 0                                            
17 VerifyCookie 0 4                                            
18 Git 0 1                                            
Bölüm Noop 0 0                                            

20
'COLLATE NOCASE' ile tablo oluşturduktan sonra, WHERE name = 'someone' COLLATE NOCASE sorgusundan çok daha hızlı olduğunu fark ettim . ÇOK daha hızlı (altı ila 10 kez, kabaca?)
DefenestrationGün

10
Belgelere göre COLLATE NOCASE, alanın zaten bu harmanlama tanımlanmışsa dizine ekleme yapılması gerekmez: " Varsayılan harmanlama sırası, CREATE TABLE ifadesinde bu sütun için tanımlanan harmanlama
sırasıdır

29
COLLATE NOCASEyalnızca ASCII metinleriyle çalışır. Sütun değerlerinizde "FIANCÉ" veya "voilà" varsa, "nişanlı" veya "VOILA" ile eşleşmez. ICU uzantısını etkinleştirdikten sonra büyük / LIKEküçük harfe duyarsız hale gelir , bu yüzden 'FIANCÉ' LIKE 'fiancé'doğrudur, ancak 'VOILA' LIKE 'voilà'yine de yanlıştır. Ve YBÜ + LIKE, endeksi kullanmama dezavantajına sahiptir, bu nedenle büyük tablolarda yavaş olabilir.

div seçin, div = 'başarısız' durumunda sonra 'BAŞARISIZ' başka 'PASSED' sonu, * işaretlerinden harmanlayın nocase yukarıdaki işe yaramadı mı?
Thunder

7
Beni tetikleyen bir şey var: select * from tbl where firstname='john' and lastname='doe' COLLATE NOCASEbüyük / küçük harfe duyarsız olacak lastname. Harf duyarsız olmak için firstname, bunu yazmak: select * from tbl where firstname='john' COLLATE NOCASE and lastname='doe'. Tüm wherecümleye değil, o sütuna özgüdür .
James Toomey

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

5
Eğer benim gibi olan ve harmanlama daha fazla doküman istiyorsanız, yapılanları bu sayfada bulabilirsiniz: sqlite.org/datatype3.html Sadece # 6.0 için aşağı kaydırın
Will

47

Bunu şu şekilde yapabilirsiniz:

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

(O değil çözüm, ancak bazı durumlarda çok uygundur)

" LIKE operatörü bir desen eşleştirme karşılaştırması yapar. Sağdaki işlenen desen içerir, soldaki işlenen desenle eşleşecek dizeyi içerir. Desendeki yüzde sembolü ("% ") sıfır veya daha fazla diziyle eşleşir Desendeki bir alt çizgi ("_"), dizedeki herhangi bir karakterle eşleşir . Başka herhangi bir karakter kendisiyle veya küçük / büyük harf eşdeğeriyle eşleşir (örn. büyük / küçük harf duyarsız eşleme) . (Bir hata: SQLite yalnızca anlar ASCII karakterleri için büyük / küçük harf LIKE işleci, ASCII aralığının ötesindeki unicode karakterler için büyük / küçük harfe duyarlıdır.Örneğin, 'a' LIKE 'A' ifadesi TRUE olur ancak 'æ' LIKE 'Æ'yanlış.)."


@ MM-BB evet, LIKE'i COLLATE NOCASE olarak bildirilen (veya dizine alınan) bir sütunda gerçekleştirmedikçe, satırların tam taramasını yapar.
Nick Dandoulakis

1
Bu bir hata değil, belgelenmiş bir sınırlamadır. Yanıtta verilen aynı sayfada unicode karakterleri yöneten ICU uzantısından bahsedilmektedir. (Belki de 2009'da durum böyle değildi)
stenci

40

Bu sqlite'a özgü değildir, ancak

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

Performans kaygısının diğer bir kısmı tablodaki eşleşen satırları bulmaktır. SQLite3 işlev tabanlı dizinleri destekliyor mu? Böyle bir durumda arama sütununu veya ifadesini (ör. "ÜST (ad)") dizine eklemek genellikle iyi bir fikirdir.
cheduardo

13
Cheduardo'nun ima ettiği gibi, SQLite bu sorguyu çalıştırırken 'name' üzerindeki bir dizini kullanamaz. Db motoru, tüm 'isim' alanlarını büyük harfe çevirerek ve karşılaştırmayı çalıştırarak tüm satırları tam olarak taramalıdır.
Mathew Waters

1
@ nicelik, evet, çok.
Berga

4

Başka bir seçenek de kendi özel harmanlamanızı oluşturmaktır. Daha sonra bu harmanlamayı sütunda ayarlayabilir veya seçtiğiniz cümlelere ekleyebilirsiniz. Sipariş ve karşılaştırmalar için kullanılacaktır.

Bu, 'VOILA' GİBİ 'voilà' yapmak için kullanılabilir.

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

İlk dize, sırasıyla ikinci dizeden küçük, eşit veya büyükse, harmanlama işlevi negatif, sıfır veya pozitif bir tamsayı döndürmelidir.


2

Sizin durumunuzda mantıklı gelebilecek veya gelmeyebilecek bir başka seçenek de, mevcut sütununuzun önceden düşük değerli değerlerine sahip ayrı bir sütuna sahip olmaktır. Bu, SQLite işlevi kullanılarak doldurulabilir LOWER()ve bunun yerine bu sütunda eşleştirme yapabilirsiniz.

Açıkçası, fazlalık ve tutarsızlık potansiyeli ekler, ancak verileriniz statikse uygun bir seçenek olabilir.


2

Basitçe, SELECT sorgunuzda COLLATE NOCASE kullanabilirsiniz:

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

1

Sütun chartürdeyse, boşluklarla sorguladığınız değeri eklemeniz gerekir, lütfen buradaki soruya bakın . Bu COLLATE NOCASEveya diğer çözümlerden birine (upper (), vb.) Ek olarak.



0

Benim için çalışıyor Mükemmel. SELECT NAME FROM TABLE_NAME WHERE NAME = 'test Name' COLLATE NOCASE

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.