Domanda

Quando si utilizza SQL, ci sono vantaggi nell'utilizzo = in un WHERE clausola invece di LIKE?

Senza operatori speciali, LIKE E = sono uguali, vero?

È stato utile?

Soluzione

diversi operatori

LIKE e = sono diversi operatori. La maggior parte delle risposte qui si concentrano 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 stringhe intere .

LIKE è un operatore di stringa che mette a confronto carattere per carattere .

A complicare le cose, sia per gli operatori utilizzano un che può avere importanti effetti sul risultato del confronto.

Motivare 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 esegui corrispondenza su una base per-caratteri, quindi può produrre risultati diversi dall'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 prega di notare che questa pagina del manuale di MySQL è chiamato Funzioni stringa di confronto , e = non si discute, il che implica che = non è strettamente una funzione di confronto di stringa.

Lavoro Come funziona =?

Il SQL standard § 8.2 descrive come = confronto 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, allora la stringa più corta è efficace   sostituito, ai fini del confronto, con una copia del   sé che è stata estesa alla lunghezza del più lungo   stringa di concatenazione a destra di uno o più pad   caratteri, dove il carattere di riempimento viene scelta in base CS. Se   CS ha l'attributo PAD NO, allora il personaggio è un pad   Tipiche attuazione-dipendente diverso da qualsiasi   carattere nel set di caratteri di X e Y che raccoglie meno   di qualsiasi stringa di sotto CS. In caso contrario, il personaggio è un pad   .

     

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

     

c) A seconda della sequenza di collazione, due stringhe può   risultano uguali anche se sono di lunghezze diverse o   contenere diverse sequenze di caratteri. Quando le operazioni   MAX, MIN, DISTINCT, riferimenti a una colonna di raggruppamento, e la   UNION, EXCEPT e INTERSECT operatori riferiscono a carattere   stringhe, il valore specifico selezionato da tali operazioni da   un insieme di tali valori uguali dipende dall'implementazione.

(corsivo è mio.)

Che cosa significa questo? Ciò significa che quando si confrontano le stringhe, l'operatore = è solo un wrapper sottile intorno il confronto corrente. Le regole di confronto è una libreria che ha varie regole per il confronto stringhe. Ecco un esempio di un confronto binario 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 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 i confronti più avanzate.

Per esempio, ecco un UTF- 8 collazione che supporta i confronti case-insensitive. Il codice è troppo lunga per incollare qui, ma andare a quel link e leggere il corpo di my_strnncollsp_utf8mb4(). Questo confronto può elaborare più byte alla volta e può applicare vari trasformazioni (come confronto case insensitive). L'operatore = è completamente sottrattodai capricci della collazione.

Lavoro Come funziona LIKE?

Il SQL standard § 8.5 descrive come LIKE confronto stringhe:

  

Il

     

M LIKE P

     

è vero se esiste una compartimentazione del M in sottostringhe   in modo tale che:

     

i) una stringa di m è una sequenza di 0 o più contigui    s di M e ogni carattere <   Rappresentazione> di M è parte di esattamente un sottostringa.

     

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

     

iii) Se la i-esima sottostringa specificatore di P è una stringa arbitraria   specificatore, allora la stringa i-esima di M è qualsiasi sequenza di   0 o più s.

     

iv) Se l'i-esima sottostringa specificatore di P è né un   specificatore carattere arbitrario né uno specificatore stringa arbitraria,   quindi la stringa i-esima di M è uguale a quella sottostringa   specificatore secondo la sequenza di collazione di   la , senza l'apposizione di   caratteri a M, e ha la stessa lunghezza di quello sottostringa   specificatore.

     

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

(corsivo è mio.)

Questo è abbastanza prolisso, quindi cerchiamo di scomposizione. Articoli II e III riferimento al jolly _ e %, rispettivamente. Se P non contiene caratteri jolly, allora solo punto iv applica. Questo è il caso di interessi posta dalla OP.

In questo caso, si confronta ogni "stringa" (singoli personaggi) in M contro ogni stringa nel P utilizzando le regole di confronto corrente.

Conclusioni

La linea di fondo è che quando si confrontano stringhe, = confronta l'intera stringa, mentre LIKE confronta un carattere alla volta. Entrambi i confronti utilizzano le regole di confronto corrente. Questa differenza porta a risultati diversi in alcuni casi, come evidenziato nel primo esempio in questo post.

Che uno si dovrebbe utilizzare? Nessuno può dire che - è necessario utilizzare quello che è corretto per il caso d'uso. Non prematuramente ottimizzare passando operatori di confronto.

Altri suggerimenti

operatore

I uguale (=) è un "operatore di confronto confronta due valori per l'uguaglianza". In altre parole, in un'istruzione SQL, esso non ritorna vero a meno che entrambe le parti dell'equazione sono uguali. Ad 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." Ad esempio:

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

LIKE è in genere utilizzato solo con le stringhe e equals (credo) è più veloce. L'operatore uguale tratta 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';

Ci tornerei 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%';

Ci tornerei 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".

La speranza che aiuta. Alcune buone informazioni si possono trovare qui .

LIKE e = sono diversi. LIKE è quello che si usa in una query di ricerca. Permette anche i caratteri jolly come _ (semplice carattere jolly) e % (jolly più caratteri).

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

Questo sito spiega LIKE

Questo è un copia / incolla di un'altra risposta di miniera per domanda 'come' vs '=' prestazioni :

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

.

Quando si utilizza una come su un indice come sottostante (nessun jolly), ci sono voluti circa 30 secondi:

where login like '12345678'

usando 'spiegare' ottengo:

entrare descrizione dell'immagine qui

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

where login ='12345678'

Utilizzando 'spiegare' ottengo:

entrare descrizione dell'immagine qui

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

.

Una differenza - oltre alla possibilità di utilizzare wildcards con SIMILE - è in spazi finali: L'operatore = ignora spazio finale, ma come no

Dipende dal sistema di database.

In generale, senza caratteri speciali, sì, = e simile sono gli stessi.

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

Per esempio, nel confronto con MySQL = sulle stringhe è sempre per difetto maiuscole e minuscole, così simile senza caratteri speciali è lo stesso. Su come quella di qualche altro RDBMS è-case insensitive mentre = non sia.

Per questo esempio diamo per scontato che varcharcol non contiene '' e non hanno alcuna 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'intero elenco. = È rigorosamente match caso mentre come si comporta come un filtro. se filtro ha nessun criterio, ogni dati sono validi.

come -. Per la virtù del suo scopo funziona un po 'più lento ed è progettato per essere utilizzato con i dati varchar e simili

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

Uso di "=" è 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 "COME ", e quindi utilizzando il 'query' / 'Includi piano di esecuzione vera e propria'.

Eseguire i due query e si dovrebbe vedere i risultati due volte, più i due piani di esecuzione effettivi. Nel mio caso, sono stati dividere il 50% contro il 50%, ma il "=" piano di esecuzione ha un più piccolo "costo sottostruttura stimato" (visualizzato quando si passa sopra la casella "SELECT" più a sinistra) - ma ancora una volta, è davvero non una grande differenza.

Ma quando si inizia la ricerca con caratteri jolly nella tua espressione LIKE, prestazioni di ricerca sarà dimish. Cerca "LIKE Mulino%" può ancora essere abbastanza veloce - SQL Server può utilizzare un indice su quella colonna, se ce n'è uno. Ricerca "LIKE% espressione%" è terribilmente lento, dal momento che l'unico modo di SQL Server è in grado di soddisfare questa ricerca è quello di eseguire una scansione completa della tabella. Quindi state attenti con il vostro simile di!

Marc

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

Questo rende la vita del programmatore più facile per non dover fuggire tutti i caratteri speciali jolly che potrebbe intrufolarsi nella clausola LIKE e che non producono il risultato previsto. Dopo tutto, = è lo scenario caso d'uso del 99%, sarebbe un dolore di dover sfuggire ogni volta.

rotola occhi a '90s

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

Per affrontare la domanda iniziale per quanto riguarda le prestazioni, si tratta di utilizzo index . Quando si verifica una semplice scansione di tabella, "come" e "=" sono identico . Quando gli indici sono coinvolti, dipende su come si forma la clausola LIKE. Più in particolare, qual è la posizione del jolly (s)?


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 realizzazione del piano di query quando si utilizza "=" vs "LIKE".

Oltre alle wildcard, la differenza tra = E LIKE dipenderà sia il tipo di SQL server e del 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 '
  • Uso MS SQL Server 2012 , gli spazi finali verranno ignorati in il confronto, se non con LIKE quando il tipo di colonna è VARCHAR.

  • MySQL 5.5 , gli spazi finali verranno ignorate per =, ma non per LIKE, entrambi con CHAR e VARCHAR.

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

    Il comportamento con LIKE differisce con CHAR.

    Utilizzando gli stessi dati come sopra, utilizzando un CAST esplicito sul nome della colonna fa anche una 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)
    

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

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 i caratteri jolly da utilizzare nella query, mi consiglia di utilizzare come solo se l'ingresso contiene una delle wild card. In caso contrario, utilizzare il uguale standard per il confronto.

Con i migliori saluti ...

In realtà si tratta di ciò che si desidera la query fare. Se vuoi dire una corrispondenza esatta quindi utilizzare =. Se vuoi dire una corrispondenza più confusa, quindi utilizzare LIKE. Dire quello che vuoi dire di solito è una buona politica con il codice.

In Oracle, un ‘come’ senza jolly restituirà lo stesso risultato di un ‘uguale’, ma potrebbe richiedere ulteriori elaborazioni. Secondo Tom Kyte , Oracle tratterà di un 'come' senza caratteri jolly come un 'uguale' quando si utilizza letterali, ma non quando si utilizza le variabili di bind.

= E LIKE non è lo stesso;

  1. = corrisponde alla stringa esatta
  2. LIKE corrisponde a una stringa che può contenere caratteri jolly (%)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top