Uguale (=) a LIKE


282

Quando si utilizza SQL, ci sono dei vantaggi nell'uso =di una WHEREclausola anziché LIKE?

Senza operatori speciali, LIKEe =sono gli stessi, giusto?


4
Potrebbe voler specificare un tipo di db ... mssql, mysql, oracle?
Allen Rice,

1
La tua domanda ha almeno 5voti per il tag like-operator . Potrei richiedere gentilmente di suggerire sql-like come sinonimo ?
Kermit

@FreshPrinceOfSO, lo farò quando avrò abbastanza reputazione. Grazie.
Travis,

Risposte:


271

Operatori diversi

LIKEe =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 LIKEfunziona?

Lo standard SQL § 8.5 descrive come LIKEconfronta 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 Pnon 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) Mrispetto a ciascuna sottostringa Pnell'uso delle regole di confronto correnti.

conclusioni

La linea di fondo è che quando si confrontano le stringhe, =confronta l'intera stringa mentre LIKEconfronta 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.


4
"EQUALS confronta due pezzi di dati byte per byte": semplificato eccessivamente, e troppo spesso non vero, perché il comportamento EQUALS (=) può essere modificato con COLLATE, facendo comparare le classi di caratteri anziché i caratteri. Ad esempio, vedere dev.mysql.com/doc/refman/5.0/en/charset-collate.html (MySQL) o sqlmag.com/blog/forcing-collation-where-clause-22-jun-2011 (SQL Server).
Peter B,

11
Questa è la risposta corretta Sappiamo cosa LIKEfa, ma questa risposta spiega perfettamente che usare LIKEsenza %o _presente non è affatto lo stesso che usare =. Possa la tua risposta ricevere mille voti.
Rinogo,

1
@mehase questo non può essere vero. Se il mio campo varchar contiene il valore 'AbCdEfG', e lo faccio WHERE MyCol = 'abcdefg', ottengo ancora quella riga indietro, anche se chiaramente non sono equivalenti byte per byte
Kip

1
PeterB e @Kip sollevano entrambi buoni punti. Ho migliorato la mia risposta per cercare di spiegare in che modo le regole di confronto influiscono su questi operatori.
Mark E. Haase,

2
Questo non sembra più vero: set charset latin1; SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;dà 0 e SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;dà anche 0.
joanq,

170

L'operatore equals (=) è un "operatore di confronto confronta due valori per l'uguaglianza". In altre parole, in un'istruzione SQL, non restituirà vero a meno che entrambi i lati dell'equazione non siano uguali. Per esempio:

SELECT * FROM Store WHERE Quantity = 200;

L'operatore LIKE "implementa un confronto di corrispondenze di schemi" che tenta di far corrispondere "un valore di stringa a una stringa di schemi contenente caratteri jolly". Per esempio:

SELECT * FROM Employees WHERE Name LIKE 'Chris%';

LIKE è generalmente usato solo con stringhe e uguale (credo) è più veloce. L'operatore uguale considera i caratteri jolly come caratteri letterali. La differenza nei risultati restituiti è la seguente:

SELECT * FROM Employees WHERE Name = 'Chris';

E

SELECT * FROM Employees WHERE Name LIKE 'Chris';

Restituirebbe lo stesso risultato, anche se l'uso di LIKE richiederebbe generalmente più tempo perché è una corrispondenza del modello. Però,

SELECT * FROM Employees WHERE Name = 'Chris%';

E

SELECT * FROM Employees WHERE Name LIKE 'Chris%';

Restituirebbe risultati diversi, quando l'uso di "=" si traduce solo in risultati con "Chris%" restituito e l'operatore LIKE restituirà qualsiasi cosa che inizia con "Chris".

Spero che aiuti. Alcune buone informazioni possono essere trovate qui .


108
Ho l'impressione che l'OP sappia quando usare LIKE e quando usare =, si sta solo chiedendo se c'è una differenza di prestazioni quando non ci sono caratteri jolly. Questa risposta tocca brevemente questo, ma ritengo che il 95% di questa risposta non sia realmente pertinente.
Programmatore fuorilegge il

1
Verissimo. Non sono sicuro che la domanda fosse la stessa quando ho risposto. Se lo fosse, mi mancava la parte che chiedeva della performance. Grazie per l'osservazione.
Achinda99,

9
Questa risposta è terribile. LIKE e '=' sono operatori completamente distinti, ma si comportano in modo simile in alcuni piccoli sottogruppi di casi. Per motivi di posteri, leggi le altre risposte qui, o almeno google per "mysql like" prima di impegnarlo in memoria.
Mark E. Haase,

3
D'altra parte, questa risposta ha risposto alla domanda che avevo e cercavo su Google. A volte è altrettanto buono se una risposta risponde al titolo di una domanda, come il contenuto.
Coray,

Una buona idea da ricordare è quando si usano char e varchar2. Se confronti char e char. Prima di confrontare il database, prima converti la lunghezza della prima 'variabile' alla stessa del secondo. Se si confrontano char e varchar2 il database non farà nulla. docs.oracle.com/cd/A64702_01/doc/server.805/a58236/c_char.htm
xild

18

Questa è una copia / incolla di un'altra mia risposta per la domanda SQL 'like' vs '=' performance :

Un esempio personale usando mysql 5.5: avevo un join interno tra 2 tabelle, una da 3 milioni di righe e una da 10 mila righe.

Quando si utilizza un like su un indice come di seguito (senza caratteri jolly), sono stati necessari circa 30 secondi:

where login like '12345678'

usando 'spiega' ottengo:

inserisci qui la descrizione dell'immagine

Quando si utilizza un '=' sulla stessa query, sono stati necessari circa 0,1 secondi:

where login ='12345678'

Usando 'spiega' ottengo:

inserisci qui la descrizione dell'immagine

Come puoi vedere, l' likeindice ha annullato completamente la ricerca, quindi la query ha impiegato 300 volte più tempo.


17

LIKEe =sono diversi. LIKEè quello che useresti in una query di ricerca. Consente inoltre caratteri jolly come _(carattere jolly semplice) e %(carattere jolly multi-carattere).

= dovrebbe essere usato se vuoi corrispondenze esatte e sarà più veloce.

Questo sito spiega LIKE


11

Una differenza - a parte la possibilità di usare i caratteri jolly con LIKE - sta negli spazi finali: l'operatore = ignora lo spazio finale, ma LIKE no.


4
Mentre questo è vero per MySQL e MS SQL, questo non è per PostgreSQL.
Bruno,

10

Dipende dal sistema di database.

Generalmente senza caratteri speciali, yes, = e LIKE sono uguali.

Alcuni sistemi di database, tuttavia, possono trattare le impostazioni di confronto in modo diverso con i diversi operatori.

Ad esempio, nei confronti di MySQL il confronto con stringhe = on è sempre senza distinzione tra maiuscole e minuscole per impostazione predefinita, quindi LIKE senza caratteri speciali è lo stesso. Su alcuni altri RDBMS il LIKE non fa distinzione tra maiuscole e minuscole mentre = non lo è.


C'è qualcosa come una panoramica di questa stranezza?
Gumbo,

9

Per questo esempio diamo per scontato che varcharcol non contenga ''e non abbia una cella vuota rispetto a questa colonna

select * from some_table where varcharCol = ''
select * from some_table where varcharCol like ''

Il primo produce un output a 0 righe mentre il secondo mostra l'intero elenco. = è rigorosamente match case mentre like si comporta come un filtro. se il filtro non ha criteri, tutti i dati sono validi.

come - in virtù del suo scopo funziona un po 'più lentamente ed è destinato all'uso con varchar e dati simili.


6

Se cerchi una corrispondenza esatta, puoi utilizzare sia, = che MI PIACE.

In questo caso l'utilizzo di "=" è un po 'più veloce (ricerca di una corrispondenza esatta): puoi verificarlo tu stesso eseguendo due volte la stessa query in SQL Server Management Studio, una volta usando "=", una volta usando "MI PIACE" e quindi utilizzando "Query" / "Includi piano di esecuzione effettivo".

Esegui le due query e dovresti vedere i risultati due volte, oltre ai due piani di esecuzione effettivi. Nel mio caso, sono stati divisi tra il 50% e il 50%, ma il piano di esecuzione "=" ha un "costo della sottostruttura stimato" più piccolo (visualizzato quando si passa con il mouse sopra la casella "SELEZIONA" più a sinistra) - ma di nuovo, è davvero non una grande differenza.

Ma quando inizi a cercare con i caratteri jolly nella tua espressione LIKE, le prestazioni di ricerca diminuiranno. Cerca "LIKE Mill%" può essere ancora piuttosto veloce: SQL Server può utilizzare un indice su quella colonna, se presente. La ricerca di "LIKE% expression%" è orribilmente lenta, poiché l'unico modo in cui SQL Server può soddisfare questa ricerca è eseguire una scansione completa della tabella. Quindi fai attenzione ai tuoi LIKE!

Marc


-1 come no, non è sempre un po 'più veloce. Se la colonna viene indicizzata usando% mystring% è un paio di ordini di grandezza più lenti. In effetti qualsiasi standard di codice degno di nota avrà linee guida rigorose su quando e quando non usarlo come su un database di mouse più grande di un micky.
Cruachan,

1
Non ho mai detto che sarebbe un po 'più lento in tutti i casi - ho detto che sarebbe un po' più lento se cerchi una corrispondenza EXACT. Di couse, la ricerca con un LIKE e l'uso di caratteri jolly, specialmente all'inizio e alla fine dell'elemento di ricerca, è MOLTO più lento, non c'è dubbio.
marc_s,

E sì, sono d'accordo - si dovrebbero avere linee guida chiare su quando usare LIKE o no (solo quando DEVI cercare con i caratteri jolly). Ma poi di nuovo - in teoria, non c'è differenza tra teoria e pratica, ma in pratica .......
marc_s,

6

L'uso di = evita conflitti tra caratteri jolly e caratteri speciali nella stringa quando si crea la query in fase di esecuzione.

Ciò semplifica la vita del programmatore non dovendo sfuggire a tutti i caratteri jolly speciali che potrebbero scivolare nella clausola LIKE e non produrre il risultato desiderato. Dopotutto, = è lo scenario del caso d'uso del 99%, sarebbe una seccatura doverli sfuggire ogni volta.

alza gli occhi agli anni '90

Sospetto anche che sia un po 'più lento, ma dubito che sia significativo se non ci sono caratteri jolly nel modello.


6

Per rispondere alla domanda originale relativa alle prestazioni, si tratta dell'utilizzo dell'indice . Quando si verifica una semplice scansione della tabella, "LIKE" e "=" sono identici . Quando sono coinvolti gli indici, dipende da come viene formata la clausola LIKE. Più specificamente, qual è la posizione dei caratteri jolly?


Considera quanto segue:

CREATE TABLE test(
    txt_col  varchar(10) NOT NULL
)
go

insert test (txt_col)
select CONVERT(varchar(10), row_number() over (order by (select 1))) r
  from master..spt_values a, master..spt_values b
go

CREATE INDEX IX_test_data 
    ON test (txt_col);
go 

--Turn on Show Execution Plan
set statistics io on

--A LIKE Clause with a wildcard at the beginning
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '%10000'
--Results in
--Table 'test'. Scan count 3, logical reads 15404, physical reads 2, read-ahead reads 15416, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index SCAN is 85% of Query Cost

--A LIKE Clause with a wildcard in the middle
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '1%99'
--Results in
--Table 'test'. Scan count 1, logical reads 3023, physical reads 3, read-ahead reads 3018, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost for test data, but it may result in a Table Scan depending on table size/structure

--A LIKE Clause with no wildcards
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '10000'
--Results in
--Table 'test'. Scan count 1, logical reads 3, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost
GO

--an "=" clause = does Index Seek same as above
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col = '10000'
--Results in
--Table 'test'. Scan count 1, logical reads 3, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost
GO


DROP TABLE test

Potrebbe esserci anche una differenza trascurabile nella creazione del piano di query quando si utilizza "=" vs "LIKE".


4

Oltre ai caratteri jolly, la differenza tra =AND LIKEdipenderà sia dal tipo di server SQL che dal tipo di colonna.

Prendi questo esempio:

CREATE TABLE testtable (
  varchar_name VARCHAR(10),
  char_name CHAR(10),
  val INTEGER
);

INSERT INTO testtable(varchar_name, char_name, val)
    VALUES ('A', 'A', 10), ('B', 'B', 20);

SELECT 'VarChar Eq Without Space', val FROM testtable WHERE varchar_name='A'
UNION ALL
SELECT 'VarChar Eq With Space', val FROM testtable WHERE varchar_name='A '
UNION ALL
SELECT 'VarChar Like Without Space', val FROM testtable WHERE varchar_name LIKE 'A'
UNION ALL
SELECT 'VarChar Like Space', val FROM testtable WHERE varchar_name LIKE 'A '
UNION ALL
SELECT 'Char Eq Without Space', val FROM testtable WHERE char_name='A'
UNION ALL
SELECT 'Char Eq With Space', val FROM testtable WHERE char_name='A '
UNION ALL
SELECT 'Char Like Without Space', val FROM testtable WHERE char_name LIKE 'A'
UNION ALL
SELECT 'Char Like With Space', val FROM testtable WHERE char_name LIKE 'A '
  • Utilizzando MS SQL Server 2012 , gli spazi finali verranno ignorati nel confronto, tranne LIKEquando è il tipo di colonna VARCHAR.

  • Usando MySQL 5.5 , gli spazi finali saranno ignorati per =, ma non per LIKE, sia con CHARche VARCHAR.

  • Utilizzando PostgreSQL 9.1 , gli spazi sono significativi sia con =e LIKEutilizzando VARCHAR, ma non con CHAR(vedi documentazione ).

    Anche il comportamento con LIKEdifferisce da CHAR.

    Utilizzando gli stessi dati di cui sopra, anche l'uso di un esplicito CASTsul nome della colonna fa la differenza :

    SELECT 'CAST none', val FROM testtable WHERE char_name LIKE 'A'
    UNION ALL
    SELECT 'CAST both', val FROM testtable WHERE
        CAST(char_name AS CHAR) LIKE CAST('A' AS CHAR)
    UNION ALL
    SELECT 'CAST col', val FROM testtable WHERE CAST(char_name AS CHAR) LIKE 'A'
    UNION ALL
    SELECT 'CAST value', val FROM testtable WHERE char_name LIKE CAST('A' AS CHAR)

    Ciò restituisce solo le righe per "CAST Both" e "CAST col".


2

La parola chiave LIKE ha indubbiamente un "cartellino del prezzo delle prestazioni". Detto questo, se si dispone di un campo di input che potrebbe potenzialmente includere caratteri jolly da utilizzare nella query, si consiglia di utilizzare LIKE solo se l'input contiene uno dei jolly. In caso contrario, utilizzare lo standard uguale al confronto.

I migliori saluti...


1

In realtà dipende da cosa vuoi che faccia la query. Se intendi una corrispondenza esatta, usa =. Se intendi una partita più fuzzier, usa LIKE. Dire quello che vuoi dire è di solito una buona politica con il codice.


1

In Oracle, un "mi piace" senza caratteri jolly restituirà lo stesso risultato di un "uguale", ma potrebbe richiedere un'ulteriore elaborazione. Secondo Tom Kyte , Oracle tratterà un "like" senza caratteri jolly come un "uguale" quando si usano valori letterali, ma non quando si usano variabili di bind.


0

=e LIKEnon è lo stesso;

  1. = corrisponde alla stringa esatta
  2. LIKE corrisponde a una stringa che può contenere caratteri jolly (%)

2
Risposta insufficiente

Potrebbe essere usato senza caratteri jolly. La domanda poneva la differenza per gli stessi casi.
M-Razavi,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.