otrdiena, 2013. gada 19. februāris

Like atslēgvārds

Like atslēgvārds noder meklēšanai pēc vārda daļas un to var izmantot teksta validācijai, piemēram, rakstot pārbaudes ierobežojumus (Check Constraints). Tomēr, kā vienam tā otram gadījumam Like bieži nav tas labākais variants.

Meklēšana
Norādot Like atslēgvārdu vaicājuma Where daļā ir visai liels risks nonākt pie vaicājumiem, kas izpildās lēni un neefektīvi. Tas ir dēļ, ka veidojot izpildes plānu, tiek izmantota kolonnas statistika. Ja pēc statistikas izskatīsies, ka vaicājums atgriezīs daudz rindas, tad netiks izmantoti indeksi un tabula tiks pilnībā pārlasīta. Savukārt, ja meklē pēc vārda daļas, kas nav vārda sākums, tad statistiku vispār nevar izmantot un labus rezultātus nav vērts gaidīt.

Nemaz nerunājot par situācijām, ja kaut kas noiet greizi ar datu tipiem- piemēram Char kolonnu salīdzinot ar NChar parametru (ideju var apskatīt arī rakstā SARG optimizācija II, meklēšana char un nchar kolonnās). Izmantojot Like atslēgvārdu, sliktajā situācijā indekss vispār netiks izmantots, pat tad, ja meklē pēc vārda sākuma un pēc visa indeks būtu lietderīgs. 
 
Tādēļ pirmais, ko darīt- izvairīties no Like lietošanas, kur vien tas iespējams :). Ja tomēr nevar (alternatīvas izvērtētas? full text search?), tad censties lai meklēšana būtu pēc vārda sākuma, protams, izmantojot pareizos datu tipus un apsverot pārklājošos (covering) indeksus.

Validācija
Piemēram, telefona numura validācijai, izmantojot Like atslēgvārdu, var veidot "gana labas" pārbaudes (protams, "īstās" validācijas vajag veidot front-end daļā).
declare @tel varchar(12);
set @tel = '+3711231231'

-- Visiem jābūt cipariem
IF (@tel like '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]')
    print '10 cipari';

-- alternatīvs variants: garums 10 un visi ir cipari
IF (len(@tel) = 10 and @tel not like '%[^0-9]%')
    print 'Len ir 10, visi cipari';

-- telefonam jābūt ar "+" sākumā
IF (@tel like '[+][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]')
    print 'tel ir ar "+"';
Kāpēc tikai "gana labas?" nevis "labas"?
Kā redzams, Like izteiksmē ir iespējams norādīt intervālus derīgajiem simboliem. Bet ja gribētu būt pavisam piekasīgi, tad patiesībā intervāli ļauj iekļūt arī sliktajiem simboliem. Piemēram, šāda "371123123²" virkne šajā gadījumā tiks uzskatīta par 10 cipariem. Tādēļ uzmanīgi ar intervālu norādīšanu :). Savukārt neizmantojot intervālus, pārbaudes sanāk garas un nepārskatāmas.

Vēl šajā sakarā piebildīšu, ka reizēm pie salīdzināšanas ir vērts norādīt kolāciju. Piemēram, ja nepieciešams meklēt lielo burtu 'J'.
IF('Jānis' like '%j%')
    print 'šis visdrīzāk notiks (atkarīgs no db kolācijas)';
IF('Jānis' like '%j%' Collate Latvian_CS_AI)
    print 'Šis nenotiks';
Attiecībā uz intervāliem, spēkā ir tas pats kas ar skaitļiem. Piemēram, ja grib pārbaudīt, vai īpašvārds sākas ar lielo burtu un pārējie ir mazie burti. Šajā gadījumā būtu jāraksta visai gara izteiksme ar visu latviešu valodas burtu uzskaitījumu. Uzrakstīju izteiksmi pieņemot, ka ir tikai burti a, b un c:
Declare @Vards varchar(34);
Set @Vards = 'Baaaabccaaccccc'
IF(@Vards like '[ABC]%' Collate Latvian_CS_AI AND
    @Vards not like '_%[^abc]%' Collate Latvian_CS_AI)
    Print 'Vārds ar lielo burtu, pārējie mazie burti';
Kāpēc burtu uzskaitījums nevis intervāls un kāpēc ar intervāliem jāuzmanās? Tur der pievērst uzmanību kolācijām un simbolu secībai (piemēram, šī saite).

Nav komentāru:

Komentāra publicēšana