2009-02-12 18 views
215

Quando si utilizza SQL, ci sono dei vantaggi nell'uso di = in una clausola WHERE invece di LIKE?Uguale a (=) rispetto a LIKE

Senza operatori speciali, LIKE e = sono gli stessi, giusto?

+2

Potrebbe voler specificare un tipo di db ... mssql, mysql, oracle? –

+1

La tua domanda ha almeno 5 voti per il tag [tag: like-operator]. Potrei cortesemente chiedere di suggerire [tag: sql-like] come [sinonimo] (http://stackoverflow.com/tags/like-operator/synonyms)? – Kermit

+0

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

risposta

173

diversi operatori

LIKE e = sono diversi operatori. La maggior parte delle risposte qui si concentra sul supporto con 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 il carattere per il carattere.

Per complicare le cose, entrambi gli operatori utilizzano uno collation che può avere effetti importanti sul risultato del confronto.

Motivating Esempio

di prima identificare un esempio in cui questi operatori producono risultati ovviamente diversi Let. Permettetemi di citare dal manuale di MySQL:

Per lo standard SQL, COME eseguito l'adattamento in base al carattere, quindi può produrre risultati diversi da parte dell'operatore = 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 | 
+--------------------------------------+ 

Si noti che questa pagina del manuale MySQL si chiama . Le funzioni di confronto delle stringhe e = non sono discusse, il che implica che = non è strettamente una funzione di confronto delle stringhe.

Come funziona =?

Il SQL Standard § 8.2 descrive come = confronta le stringhe:

Il confronto di due stringhe di caratteri è determinato come segue:

a) Se la lunghezza in caratteri di X non è uguale alla lunghezza in caratteri di Y, quindi la stringa più breve è efficacemente sostituita, a fini di confronto, con una copia di stessa estesa alla lunghezza della stringa più lunga mediante concatenazione a destra di uno o più pad caratteri, in cui il carattere 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 è un .

b) Il risultato del confronto di X e Y è data dalla sequenza di confronto CS.

c) A seconda della sequenza di collazione, due stringhe possono risultano uguali anche se sono di lunghezze differenti o contengono diverse sequenze di caratteri. Quando le operazioni MAX, MIN, DISTINCT fanno riferimento a una colonna di raggruppamento e gli operatori UNION, EXCEPT e INTERSECT si riferiscono alle stringhe di carattere , il valore specifico selezionato da queste operazioni da un insieme di tali valori uguali è l'implementazione- dipendente.

(corsivo è mio.)

Cosa significa? Significa che quando si confrontano le stringhe, l'operatore = è solo un involucro sottile attorno alle regole di confronto correnti. Un confronto è una libreria che ha varie regole per confrontare le stringhe. Ecco un esempio di a binary collation from 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 particolare collazione accade per confrontare byte per byte (che è il motivo per cui si chiama "binario" - non dà alcun significato speciale per le stringhe). Altre regole di confronto possono fornire confronti più avanzati.

Ad esempio, ecco uno UTF-8 collation che supporta confronti senza distinzione tra maiuscole e minuscole. Il codice è troppo lungo da incollare qui, ma vai a quel link e leggi il corpo di my_strnncollsp_utf8mb4(). Questo confronto può elaborare più byte alla volta e può applicare varie trasformazioni (come il confronto senza distinzione tra maiuscole e minuscole). L'operatore = è completamente astratto dai capricci della collazione.

Come funziona LIKE?

Il SQL Standard § 8.5 descrive come LIKE confronta le stringhe:

Il <predicato>

M LIKE P

vale se esiste una partizione di M in sottostringhe tale che:

i) Una sottostringa di M è una sequenza di 0 o mo re contigua < rappresentazione di carattere > s di M ed ogni < carattere rappresentazione > di M fa parte di esattamente un sottostringa.

ii) Se la i-esima sottostringa specificatore di P è un arbitrario specificatore carattere, la stringa i-esima di M è un singolo < rappresentazione di carattere >.

iii) Se la i-esima sottostringa specificatore di P è un arbitrario stringa specificatore, allora la stringa i-esima di M è qualsiasi sequenza di 0 o più < rappresentazione di carattere > s.

iv) Se la i-esima sottostringa specificatore di P è né un arbitrario specificatore carattere né uno specificatore stringa arbitraria, quindi la stringa i-esima di M è uguale a quella stringa specificatore secondo la sequenza di collazione di > come il predicato >, senza l'aggiunta di <spazio> caratteri a M, e ha la stessa lunghezza di quella sottostringa identificatore .

v) Il numero di sottostringhe di M è uguale al numero di specificatori di sottostringa di P.

(enfasi aggiunta).

Questo è abbastanza prolisso, quindi cerchiamo di scomposizione. Gli articoli ii e iii si riferiscono ai caratteri jolly _ e %, rispettivamente. Se P non contiene caratteri jolly, verrà applicato solo l'articolo iv. Questo è il caso di interesse posto dal PO.

In questo caso, confronta ciascuna "sottostringa" (singoli caratteri) in M in corrispondenza di ciascuna sottostringa in P utilizzando le 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 le regole di confronto correnti. Questa differenza porta a risultati diversi in alcuni casi, come evidenziato nel primo esempio in questo post.

Quale dovresti usare? Nessuno può dirti questo: devi usare quello corretto per il tuo caso d'uso. Non ottimizzare preventivamente passando da operatori di confronto.

+3

"UGUALI confronta due byte di dati byte per byte": eccessivamente semplificato, e troppo spesso non vero, perché Il comportamento di EQUALS (=) può essere modificato con COLLATE, causando il confronto tra classi di caratteri e caratteri. Per esempio. vedi http://dev.mysql.com/doc/refman/5.0/en/charset-collate.html (MySQL) o http://sqlmag.com/blog/forcing-collation-where-clause-22-jun- 2011 (SQL Server). –

+7

* Questa * è la risposta corretta. Sappiamo cosa fa 'LIKE', ma questa risposta spiega in modo fantastico che l'uso di' LIKE' senza '%' o '_' present è * not affatto * lo stesso che usare' = '. Possa la tua risposta ricevere migliaia di voti. – rinogo

+1

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

5

Utilizzo = evita i caratteri jolly e i conflitti di caratteri speciali nella stringa quando si genera la query in fase di esecuzione.

Ciò semplifica la vita del programmatore evitando di scappare da tutti i caratteri jolly speciali che potrebbero scivolare nella clausola LIKE e non produrre il risultato desiderato. Dopotutto, = è il caso d'uso del 99%, sarebbe un dispiacere doverli sfuggire ogni volta.

rotea gli occhi al '90

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

0

= e LIKE non è la stessa;

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

Risposta insufficiente –

10

Una differenza - a parte la possibilità di utilizzare i caratteri jolly con LIKE - è in spazi finali: Il = l'operatore ignora lo spazio finale, ma LIKE non lo fa.

+4

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

1

In realtà si tratta di ciò che si desidera che la query faccia. Se intendi una corrispondenza esatta, usa =. Se intendi una corrispondenza più confusa, usa LIKE. Dire cosa intendi di solito è una buona politica con il codice.

8

Dipende dal sistema di database.

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

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

Ad esempio, nei confronti di MySQL con = su stringhe è sempre case-insensitive di default, quindi LIKE senza caratteri speciali è lo stesso. Su alcuni altri RDBMS LIKE non fa distinzione tra maiuscole e minuscole mentre = non lo è.

+0

C'è qualcosa come una panoramica per questa stranezza? – Gumbo

+0

controlla i documenti per qualunque sistema rdbms stai usando –

16

LIKE e = sono diversi. LIKE è ciò che useresti in una query di ricerca. Permette anche caratteri jolly come _ (carattere jolly semplice) e % (carattere jolly a più caratteri).

= deve essere utilizzato se si desidera corrispondenze esatte e sarà più veloce.

This site explains LIKE

4

Se si cerca una corrispondenza esatta, è possibile utilizzare sia, = e LIKE.

Utilizzando "=" è un pochino più veloce in questo caso (alla ricerca di una corrispondenza esatta) - è possibile controllare da soli avendo la stessa query due volte in SQL Server Management Studio, una volta utilizzando "=", una volta usando " LIKE ", quindi utilizzando la" Query "/" Includi piano di esecuzione effettivo ".

Esegui le due query e dovresti vedere i risultati due volte, più i due piani di esecuzione effettivi. Nel mio caso, sono stati divisi il 50% contro il 50%, ma il piano di esecuzione "=" ha un "costo del sottostrato stimato" più piccolo (visualizzato quando si passa con il mouse sopra la casella "SELECT" più a sinistra) - ma di nuovo, è davvero non un'enorme differenza.

Ma quando si avvia la ricerca con caratteri jolly nell'espressione LIKE, la performance della ricerca diminuirà. La ricerca "LIKE Mill%" può essere ancora abbastanza veloce: SQL Server può utilizzare un indice su quella colonna, se ce n'è uno. La ricerca "LIKE% expression%" è orribilmente lenta, poiché l'unico modo in cui SQL Server può soddisfare questa ricerca è eseguendo una scansione completa della tabella. Quindi stai attento con i tuoi LIKE!

Marc

+0

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

+0

Non ho mai detto che sarebbe stato un po 'più lento per tutti i casi - ho detto che sarà un po' più lento se si cerca una corrispondenza ESATTA. Di couse, la ricerca con un MI PIA e l'uso di caratteri jolly, specialmente all'inizio e alla fine della ricerca, è MOLTO più lento, non c'è dubbio. –

+0

E sì, sono d'accordo - uno * dovrebbe * avere chiare linee guida su quando usare LIKE o meno (solo quando è NECESSARIO cercare con caratteri jolly). Ma poi di nuovo - in teoria, non c'è differenza tra teoria e pratica, ma in pratica ....... –

2

La parola chiave LIKE viene fornito senza dubbio con un "andamento dei prezzi-tag" allegata. 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 caratteri jolly. Altrimenti, usa lo standard uguale al confronto.

migliori saluti ...

164

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

SELECT * FROM Store WHERE Quantity = 200; 

L'operatore LIKE "implementa un modello di confronto match" che tenta di corrispondere "un valore di stringa contro una stringa modello contenente caratteri jolly." Per esempio:

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

LIKE è in genere utilizzato solo con le stringhe e equals (credo) è più veloce. L'operatore di uguali tratta i caratteri jolly come caratteri letterali. La differenza di risultati restituiti sono i seguenti:

SELECT * FROM Employees WHERE Name = 'Chris'; 

E

SELECT * FROM Employees WHERE Name LIKE 'Chris'; 

sarebbe tornato lo stesso risultato, pur usando COME sarebbe generalmente necessario più tempo perché è un pattern match. Tuttavia,

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

E

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

sarebbe tornato risultati diversi, in cui l'utilizzo di "=" si traduce in risultati solo con "Chris%" ritorno, e che l'operatore LIKE tornerà tutto ciò che inizia con "Chris" .

Spero che questo aiuti. Alcune buone informazioni possono essere trovate here.

+105

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 è presente alcun carattere jolly. Questa risposta tocca brevemente questo aspetto, ma ritengo che il 95% di questa risposta non sia realmente pertinente. –

+1

Molto vero. Non sono sicuro che la domanda fosse la stessa quando ho risposto. Se lo fosse, mi è mancata la parte che mi ha chiesto dello spettacolo. Grazie per l'osservazione. – achinda99

+9

Questa risposta è terribile. LIKE e '=' sono operatori completamente distinti, ma semplicemente si comportano in modo simile in alcuni sottogruppi di casi. Per motivi di posterità, ti preghiamo di leggere il resto delle risposte qui, o almeno di google per "mysql like" prima di commetterlo in memoria. –

6

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


Si consideri il seguente:

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 

Ci possono essere anche differenze trascurabili nella creazione del piano di query quando si utilizza "=" vs "LIKE".

1

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

3

Oltre ai caratteri jolly, la differenza tra = E LIKE dipenderà dal tipo di server SQL e dal tipo di colonna.

Prendete 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 saranno ignorati nel confronto, se non con LIKE quando il tipo di colonna è VARCHAR.

  • Utilizzando MySQL 5.5, gli spazi finali saranno ignorati per =, ma non per LIKE, entrambi con CHAR e VARCHAR.

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

    Anche il comportamento con LIKE differisce da CHAR.

    Utilizzando gli stessi dati come sopra, con un esplicito CAST sul nome della colonna also makes a difference:

    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) 
    

    Questo solo restituisce le righe per "CAST entrambi" e "CAST col".

8

Per questo esempio prendiamo per scontato che varcharcol non contiene '' e non hanno cella vuota contro questa colonna

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

I primi risultati in uno 0 uscita fila mentre la seconda mostra l'intera lista. = è rigorosamente match case mentre like funge da filtro. se il filtro non ha criteri, tutti i dati sono validi.

come - dal punto di vista del suo scopo funziona un po 'più lentamente ed è inteso per l'uso con dati varchar e simili.

12

Questo è un copia/incolla di un'altra risposta di miniera per domanda SQL 'like' vs '=' performance:

Un esempio personale utilizzando MySQL 5.5: ho avuto un inner join tra 2 tabelle, una di 3 milioni di righe e uno di 10 mila righe .

Quando si utilizza un simile su un indice, come di seguito (nessun jolly), ci sono voluti circa 30 secondi:

where login like '12345678' 

usando 'spiego' ottengo:

enter image description here

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

where login ='12345678' 

Utilizzo 'exp lain' ottengo:

enter image description here

Come si può vedere, la like completamente cancellato l'indice di ricerca, in modo da query ha 300 volte più tempo.