MySQL kis- és nagybetűk megkülönböztetése

mysql logo

Tudjuk vagy sem, de MySQL-ben a mező választott karakterkészletétől függ, hogy kereséskor egy WHERE feltételben számít-e a kis- és nagybetűk különbsége. Elsőre lehet nem tűnik fontosnak ez a kérdés. De cseppet sem mindegy, hogy egy loginrendszernél például ugyanannak számít-e Bela és bela. Ugyanakkor egy jelszónál ( amit egyébként nem nagyon szokás hashelés nélkül tárolni ) pedig fontos, hogy különbözzön 123ABC és 123aBc. Most nem tudok jobb példát mondani. De akkor milyen karakterkészletet válasszunk? Erről fogok írni pár szót.


Egy részt el kell dönteni a karakterkódolást, hogy valamilyen latin készletet használunk-e, esetleg UTF-et. Ezeken belül találkozhatunk különböző végződésekkel. Például _ci (Case Insensitive), _cs (Case Sensitive) vagy _bin (Binary). Utóbbi két esetben A "b" és a "B" különbözőnek számít. Tehát a következő lekérdezés

select * from sutik where nev = 'Kürtöskalács'

nem találná meg a "kürtöskalács" nevű sütiket. Ellenben a _ci végződésűeknél még az ékezet sem számít. Ami még keresésnél is hasznos.

Én már választottam karakterkészletet, de mindkét módszert szeretném használni.
Erre is van megoldás. Egyik lehetőség, hogy lekérdezzük az összes rekordot, és a használt programnyelven alkalmazható módszerekkel hasonlítjuk össze a két sztringet. Lehet ez valamilyen reguláris kifejezés, vagy mindkét összehasonlítandó karakterláncot előbb kisbetűssé alakítjuk, és azt hasonlítjuk össze. Nem biztos, hogy ez a legjobb megoldás, de lehetőségnek adott.

Kisbetűssé alakítással
A másik lehetőség, hogy már SQL-ben elvégezzük a "kisbetűsítést".

select * from tabla where lcase(mezo1) = "kisbetűsszöveg";

Az lcase függvénnyel a mező tartalmát kisbetűssé lehet alakítani. Viszont ettől még az ékezetek különbsége ugyanúgy számít.

Ékezetek sem különböznek
ha konvertáljuk a lekérdezésben a mező tartalmát C.S. -ről C.I. -re vagy fordítva. Erre ugyanaz a collate kulcsszó a megoldás, mint amivel a mezők karakterkódolását már a tábla létrehozásakor is meg lehet adni. Viszont itt magában a lekérdezésben utólag kényszerítjük ki.
Ha a mező karakterkódolása utf8_bin, és case insensitive összehasonlítás kell, akkor

select * from sutik where nev collate utf8_general_ci = 'Kürtöskalács'

Ha pedig a helyzet pont fordított, és egy utf8_general_ci karakterkódolású mezőnél akarunk case sensitive összehasonlítást, akkor

select * from sutik where nev collate utf8_bin = 'Kürtöskalács'

Mindent összevetve, én azt javaslom, hogy használjunk valamilyen _ci végződésű karakterkészletet. És ha nagy ritkán szükség lenne másfajta összehasonlításra, akkor kikényszeríthető. De szerintem ez ritkább eset, mint a fordítottja.

Kategóriák: 
Megosztás/Mentés

Hozzászólások

klank képe

Na, most legalább már ezt is tudom! Eddig még nem is gondoltam ilyenekre... De "jó pap holtig tanul" - tartja a közmondás. :)

Rimelek képe

Ez így van. Nekem is meg kell tanulni alaposabban átnézni a blogot elküldés előtt, mert kihagytam az utolsó két sql-nél a where kulcsszót is és a mezőnevet. A collate pedig nem a mező, hanem eszköz a konvertáláshoz. De most javítottam.

Anonymous képe

Gondolom a MySQL fulltext search eleve nem jöhet szóba, mert ott nem lehet változó collate-kat megadni

Rimelek képe

Ezen még nem gondolkodtam, de én is úgy tudom, hogy collate-ekkel nem lehet játszani ott.

UI: Valahogy erről az üzenetedről megfeledkeztem eddig.