Operatori diversi
LIKE
e =
sono operatori diversi. La maggior parte delle risposte qui si concentra sul supporto dei caratteri jolly, che non è l'unica differenza tra questi operatori!
=
è un operatore di confronto che opera su numeri e stringhe. Quando si confrontano le stringhe, l'operatore di confronto confronta intere stringhe .
LIKE
è un operatore di stringa che confronta carattere per carattere .
A complicare le cose, entrambi gli operatori utilizzano un confronto che può avere effetti importanti sul risultato del confronto.
Esempio motivante
Identifichiamo innanzitutto un esempio in cui questi operatori producono risultati ovviamente diversi. Mi permetta di citare dal manuale di MySQL:
Per lo standard SQL, LIKE esegue la corrispondenza in base al carattere, quindi può produrre risultati diversi dall'operatore di confronto =:
mysql> SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;
+-----------------------------------------+
| 'ä' LIKE 'ae' COLLATE latin1_german2_ci |
+-----------------------------------------+
| 0 |
+-----------------------------------------+
mysql> SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;
+--------------------------------------+
| 'ä' = 'ae' COLLATE latin1_german2_ci |
+--------------------------------------+
| 1 |
+--------------------------------------+
Nota che questa pagina del manuale di MySQL si chiama String Comparison Functions e =
non è discussa, il che implica che =
non è strettamente una funzione di confronto di stringhe.
Come =
funziona?
Lo standard SQL § 8.2 descrive come =
confronta le stringhe:
Il confronto tra due stringhe di caratteri è determinato come segue:
a) Se la lunghezza in caratteri di X non è uguale alla lunghezza in caratteri di Y, la stringa più corta viene effettivamente sostituita, ai fini del confronto, con una copia di se stessa che è stata estesa alla lunghezza della stringa più lunga per concatenazione a destra di uno o più caratteri pad, in cui il personaggio pad viene scelto in base a CS. Se CS ha l'attributo NO PAD, il carattere pad è un carattere dipendente dall'implementazione diverso da qualsiasi carattere nel set di caratteri di X e Y che raccoglie meno di qualsiasi stringa in CS. Altrimenti, il carattere del pad è a.
b) Il risultato del confronto tra X e Y è dato dalla sequenza di confronto CS.
c) A seconda della sequenza di fascicolazione, due stringhe possono comparare come uguali anche se hanno lunghezze diverse o contengono sequenze di caratteri diverse. Quando le operazioni MAX, MIN, DISTINCT, riferimenti a una colonna di raggruppamento e gli operatori UNION, EXCEPT e INTERSECT si riferiscono a stringhe di caratteri, il valore specifico selezionato da queste operazioni da un insieme di tali valori uguali dipende dall'implementazione.
(Enfasi aggiunta.)
Cosa significa questo? Significa che quando si confrontano le stringhe, l' =
operatore è solo un involucro sottile attorno all'attuale confronto. Una collation è una libreria che ha varie regole per confrontare le stringhe. Ecco un esempio di regole di confronto binarie da MySQL :
static int my_strnncoll_binary(const CHARSET_INFO *cs __attribute__((unused)),
const uchar *s, size_t slen,
const uchar *t, size_t tlen,
my_bool t_is_prefix)
{
size_t len= MY_MIN(slen,tlen);
int cmp= memcmp(s,t,len);
return cmp ? cmp : (int)((t_is_prefix ? len : slen) - tlen);
}
Questo confronto particolare capita di confrontare byte per byte (motivo per cui si chiama "binario" - non dà alcun significato speciale alle stringhe). Altre regole di confronto possono fornire confronti più avanzati.
Ad esempio, ecco un confronto UTF-8 che supporta confronti senza distinzione tra maiuscole e minuscole. Il codice è troppo lungo per incollarlo qui, ma vai a quel link e leggi il corpo di my_strnncollsp_utf8mb4()
. Questa raccolta può elaborare più byte alla volta e può applicare varie trasformazioni (come il confronto senza distinzione tra maiuscole e minuscole). L' =
operatore è completamente sottratto ai capricci della collazione.
Come LIKE
funziona?
Lo standard SQL § 8.5 descrive come LIKE
confronta le stringhe:
Il <predicato>
M LIKE P
è vero se esiste un partizionamento di M in sottostringhe tale che:
i) Una sottostringa di M è una sequenza di 0 o più <rappresentazioni di caratteri> contigue di M e ciascuna <rappresentazione di caratteri> di M fa parte esattamente di una sottostringa.
ii) Se l'i-esimo identificatore di sottostringa di P è un identificatore di caratteri arbitrario, l'i-esima sottostringa di M è una singola <rappresentazione di carattere>.
iii) Se l'i-esimo identificatore di sottostringa di P è un identificatore di stringa arbitrario, l'i-esima sottostringa di M è una qualsiasi sequenza di 0 o più <rappresentazione di carattere> s.
iv) Se l'i-esimo identificatore di sottostringa di P non è né un identificatore di caratteri arbitrario né un identificatore di stringa arbitrario, l'i-esima sottostringa di M è uguale a quell'identificatore di sottostringa in base alla sequenza di confronto del <predicato simile>, senza l'aggiunta di caratteri <spazio> a M e ha la stessa lunghezza dello specificatore di sottostringa.
v) Il numero di sottostringhe di M è uguale al numero di specificatori di sottostringa di P.
(Enfasi aggiunta.)
Questo è piuttosto prolisso, quindi analizziamolo. Le voci ii e iii si riferiscono ai caratteri jolly _
e %
, rispettivamente. Se P
non contiene caratteri jolly, si applica solo l'articolo IV. Questo è il caso di interesse sollevato dall'OP.
In questo caso, confronta ogni "sottostringa" (singoli caratteri) M
rispetto a ciascuna sottostringa P
nell'uso delle regole di confronto correnti.
conclusioni
La linea di fondo è che quando si confrontano le stringhe, =
confronta l'intera stringa mentre LIKE
confronta un carattere alla volta. Entrambi i confronti utilizzano l'attuale confronto. Questa differenza porta a risultati diversi in alcuni casi, come evidenziato nel primo esempio in questo post.
Quale dovresti usare? Nessuno te lo può dire: devi usare quello corretto per il tuo caso d'uso. Non ottimizzare prematuramente cambiando operatore di confronto.