Like-oljuk a LIKE-ot?

(A címért elnézést!) A relációs adatbázis azért (is) jó, mert típusos adatokat tudunk tárolni benne. Ha mondjuk egy házszámot tárolunk el és arra keresünk, akkor azt könnyű megtalálni, hogy 13. Még azt is, hogy 13/b, bár itt már lehet egy kis félreértés, ha elírás volt és “fordított perjel” került be, vagy szóköz került valahová.

De az igazi móka akkor kezdődik, ha valamit nem tudunk pontosan és egy töredék alapján szeretnénk visszakapni az eredménylistánkat. Ilyenkor jön jól a LIKE, ami egy szűrő operátor, ezért a WHERE részben használható

% (százalék)

Ez a legismertebb alkalmazása, amikor “bármit” keresünk, “bármi” hosszan. Kicsit értelmesebben kifejtve: a % helyettesítő bármilyen karaktert helyettesít, 0, 1 vagy bármilyen hosszan.

select * from tabla where mezo like 'akarmi%'

Ezzel a mezo oszlop alapján csak azokat a sorokat jelenítjük meg, aminek a tartalma “akarmi”, vagy az “akarmi” szöveggel kezdődik. Természetesen nem csak egyszer lehet használni, például:

select * from tabla where mezo like '%akarmi%'

Amivel azt tudjuk elérni, hogy az “akarmi” szöveg bárhol lehet az oszlopban, hiszen ezzel azt mondjuk, hogy “keresd meg, ahol bármi van az oszlopban, majd az akarmi szó jön és megint bármi lehet mögötte”. Lehet még bonyolítani, ha még többet használunk:

select * from tabla where mezo like '%akarmi%valami%'

Vagyis “bármi van az oszlopban, majd az akari szó, majd megint bármi, majd a valami szó, majd megint bármi”. Ezzel már óvatosabban kell bánni, mert a “bármi” tényleg bármi lehet. Egy karakter, vagy akár egy sem és minél rövidebb szövegeket adunk meg, annál nagyobbat fog harapni az adatbázisból. Például egy ‘%5%akarmi%’ illeszkedni fog az “5akarmi” de akár a “nagyonhosszu es 5 es 2 es 7 es 8 es akarmi meg a vegen is van sok minden” szövegre is.

Ha mindez nem lenne elég, akkor meg lehet fejelni a not operátorral is, ami negálja a keresést és csak azt kapjuk meg, ami nem illeszkedik a megadott szűrőre:

select * from tabla where mezo not like 'akarmi%'

_ (aláhúzás)

Ha nem szeretnénk, hogy a “bármi” rész nagyon lazán legyen kezelve és csak pár helyen szeretnénk a behelyettesítést, akkor az aláhúzást tudjuk használni, ami csak egy karaktert jelent. Nincs “bármi” a helyettesítésnél, hanem csak egy “bármilyen karakter”.

select * from tabla where mezo like 'akarmi_'

Ezzel csak azokat a sorokat kapjuk meg, amik úgy kezdődnek, hogy “akarmi” és nulla vagy egy bármilyen karakter van utána. A százalék és az aláhúzás közösen is használható és ezért az egyik tipikus hiba, ami mindig kimegy az ember fejéből, ha valóban aláhúzásra vagy százalék jelre szeretne keresni:

select * from tabla where mezo like '%akarmi_valami%'

Nem azokat a sorokat fogjuk megkapni, amiben bárhol szerepel az “akarmi_valami” szöveg! Hanem azt, ahol “bármivel kezdődik, majd az akarmi szöveg jön, majd nulla vagy egy bármilyen karakter, majd a valami szöveg és a végén bármi van”. Ezt azzal lehet áthidalni, hogy az aláhúzás karaktert szögletes zárójelekkel vesszük körbe:

select * from tabla where mezo like '%akarmi[_]valami%'

illetve meghatározhatjuk, hogy mi legyen az escape karakter, ami után pont azt kell érteni, amit írtunk

select * from tabla where mezo like '%akarmi!_valami%' escape '!'

amivel jelezzük, hogy ami a felkiáltójel után közvetlenül következő karaktert úgy kell érteni, ahogy van.

[] (szögletes zárójelek)

Ha már a szögletes zárójeleknél tartunk, akkor azt fel lehet használni másra is. Fejlesztőként mindenki legalább hallott már a reguláris kifejezésekről. Az MSSQL ha nem is kezel reguláris kifejezéseket, de valami kis alap van benne.

Ez a szögletes zárójel, amit az előbb csak egy karakterre használtunk, de valójában tartományokat is meg lehet adni. Ekkor is csak egy karakterre vonatkozik, de egy tartományból kerülhet ki.

select * from tabla where mezo like '%akarmi[a-z]valami%'

Az akarmi és a valami között egy karaktert keresünk, de az az ABC bármelyik betűje lehet. Lehet sima felsorolás is, és tudjuk negálni is, hogy például

select * from tabla where mezo like '%akarmi[^abcdef]valami%'

A ^ jel a negáló, az abcdef pedig a karakterkészlet, amit kizárunk.

Numerikus és dátum mezők

A LIKE alapvetően szöveges mezőkre való. Numerikus mezőkre is működik, de csak az egyértelmű automatikus konverzió miatt. A háttérben a feldolgozó átkonvertálja szöveggé és azon nézi az egyezést.

Ennek ellenére sokkal gyorsabb, logikusabb és egyértelműbb, ha numerikus adaton inkább a szokásos kisebb-nagyobb, egyenlő-nem egyenlő és between operátorokat használjuk.

Dátumnál nem egyértelmű a konverzió, ezért ott vagy mi konvertálunk, vagy olyan dátum-kezelő függvényeket használunk, mint a datepart vagy a month/day/year és társai. Példa konvertálásra:

select * 
from tabla 
where convert(varchar(25), datum_mezo, 23) like '2022-09-1%'

A converttel áttesszük a dátumot egy “normálisabb” formátumba és ezt hasonlítjuk össze. A convert és a dátum összefüggéseit egy szép táblázat tartalmazza.

Teljesítmény

Ha körülnéztek a neten, kismillió cikket találtok arról, hogy a LIKE lassú, mit kell figyelembe venni és hogy miért ne használjuk. Én azt mondom, mint mindig: ésszel használjuk, és feladata válogatja, hogy mikor hasznos, mikor tudunk vele élni.

A legfontosabb az indexek (mint sok más alkalommal is), amit mindenki említ és figyelembe kell venni. Ezt nem veszem végig, megér egy külön bejegyzést, csak azon gondolkozzatok el, hogy ha a “bármi” a szöveg végén van, akkor tudunk indexet használni, ha az elején, vagy közben, akkor pedig nem olyan egyszerű.