Equals (=) vs. LIKE

en utilisant SQL, y a-t-il des avantages à utiliser = dans une clause WHERE au lieu de LIKE ?

Sans opérateurs, LIKE et = sont les mêmes, non?

244
demandé sur Travis 2009-02-13 00:57:40

15 réponses

Opérateurs Différents

LIKE et = sont des opérateurs différents. La plupart des réponses ici se concentrent sur le support de Joker, ce qui n'est pas la seule différence entre ces opérateurs!

= est un opérateur de comparaison qui opère sur les nombres et les chaînes. En comparant les chaînes, l'opérateur de comparaison compare chaînes entières .

LIKE est un opérateur de chaîne qui compare caractère par caractère .

pour compliquer les choses, les deux opérateurs utilisent un collation qui peut avoir des effets importants sur le résultat de la comparaison.

Motivation "Exemple De 1519240920"

nous allons d'abord identifier un exemple où ces opérateurs produisent des résultats manifestement différents. Permettez-moi de citer le manuel MySQL:

Selon la norme SQL, comme effectue l'appariement sur une base par caractère, ainsi il peut produire des résultats différents de l'opérateur de comparaison:

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 |
+--------------------------------------+

veuillez noter que cette page du manuel MySQL est appelée String Comparison Functions , et = n'est pas discutée, ce qui implique que = n'est pas strictement une fonction de comparaison de chaîne.

Comment Fonctionne = ?

la" norme 1519540920 "SQL § 8.2 décrit comment = compare les chaînes:

La comparaison de deux chaînes de caractères est déterminée comme suit:

a) Si la longueur en caractères de X n'est pas égale à la longueur dans les caractères de Y, alors la chaîne plus courte est effectivement remplacé, à des fins de comparaison, par une copie lui-même, qui a été étendue à l' la longueur de la plus longue chaîne par concaténation à droite d'un ou plusieurs coussinets caractères, où le caractère pad est choisi en fonction de CS. Si CS a L'attribut NO PAD, alors le caractère pad est un le caractère dépendant de la mise en œuvre diffère de tout autre caractère dans le jeu de X et Y qui rassemble moins que n'importe quelle corde sous CS. Sinon, le caractère de remplissage est un .

b) le résultat de la comparaison de X et Y est donné par le séquence de collation CS.

c) Selon la séquence de collage, deux chaînes peuvent comparez comme égale même si elles sont de longueurs différentes ou contient différentes séquences de caractères. Lorsque les opérations de MAX, MIN, DISTINCT, références à une colonne de regroupement, et le Les opérateurs intersectés se réfèrent au caractère les chaînes, à la valeur sélectionnée par ces opérations de un ensemble de valeurs égales est dépendant de l'implémentation.

(non souligné dans l'original.)

Qu'est-ce que cela signifie? Cela signifie qu'en comparant les chaînes, l'opérateur = n'est qu'un mince enveloppement autour de la collation actuelle. Une collation est une bibliothèque qui a diverses règles pour comparer des chaînes. Voici un exemple de une collation binaire de 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);
}

Ce classement arrive à comparer octet-par-octet (c'est pourquoi il est appelé "binaire" - il ne donne pas de sens particulier aux chaînes). D'autres collations peuvent fournir des comparaisons plus avancées.

par exemple, voici une collation UTF-8 qui supporte des comparaisons non sensibles à la casse. Le code est trop long à coller ici, mais allez sur ce lien et lisez le corps de my_strnncollsp_utf8mb4() . Ce classement peut traiter plusieurs octets à la fois et il peut appliquer différentes transformations (comme la comparaison de la casse). Le L'opérateur = est complètement abstrait des caprices de la collation.

Comment Fonctionne LIKE ?

la "norme 1519540920" SQL § 8.5 décrit comment LIKE compare les chaînes:

M LIKE P

est vrai s'il existe un partitionnement de M en substrats tels que:

i) une sous-couche de M est une séquence de 0 ou plus contiguë < représentation des caractères>s DE M et de chaque < caractère la représentation> de M fait partie d'exactement un substrat.

ii) si le i-ième spécificateur de chaîne de P est un arbitraire spécificateur de caractère, le i-ième substrat de M est n'importe quel < représentation des caractères>.

iii) si le i-ième spécificateur de chaîne de P est une chaîne arbitraire spécificateur, puis l'i-th la soustraitance de M est toute séquence de 0 ou plus S.

iv) si le i-ième spécificateur de P n'est pas un caractère arbitraire spécificateur ni une chaîne de caractères arbitraire spécificateur, alors la i-ième sous-couche de M est égale à cette sous-couche spécificateur selon la séquence de collationnement l' , sans l'ajout de caractères à M, et a la même longueur que cette chaîne spécificateur.

v) le nombre de sous-couches de M est égal au nombre de prescripteurs des substrats de P.

(non souligné dans l'original.)

c'est assez verbeux, alors décomposons-le. Les points ii et iii renvoient respectivement aux caractères génériques _ et % . Si P ne contient pas de Joker, seul le point iv s'applique. C'est le cas de l'intérêt suscité par le PO.

dans ce cas, il compare chaque" substrat "(caractères individuels) dans M avec chaque substrat dans P en utilisant la collation courante.

Conclusions

le résultat est que lorsque l'on compare les chaînes, = compare la chaîne entière tandis que LIKE compare un caractère à la fois. Les deux comparaisons utiliser le classement actuel. Cette différence conduit à des résultats différents dans certains cas, comme en témoigne dans le premier exemple de ce post.

lequel devez-vous utiliser? Personne ne peut vous dire que vous avez besoin d'utiliser celui qui est correct pour votre cas d'utilisation. Ne pas optimiser prématurément en changeant les opérateurs de comparaison.

213
répondu Mark E. Haase 2015-01-22 17:31:10

l'opérateur equals ( = ) est un "opérateur de comparaison compare deux valeurs pour l'égalité."En d'autres termes, dans un énoncé SQL, il ne retournera pas vrai à moins que les deux côtés de l'équation sont égaux. Par exemple:

SELECT * FROM Store WHERE Quantity = 200;

L'opérateur LIKE "met en œuvre une correspondance de modèle de comparaison" qui essaie de faire correspondre une "chaîne de valeur par rapport à un modèle de chaîne de caractères contenant des caractères génériques."Par exemple:

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

comme est généralement utilisé seulement avec des cordes et des égaux (je crois) est plus rapide. L'opérateur equals traite les caractères wild-card comme des caractères littéraux. Les différences de résultats sont les suivantes:

SELECT * FROM Employees WHERE Name = 'Chris';

et

SELECT * FROM Employees WHERE Name LIKE 'Chris';

renverrait le même résultat, bien que L'utilisation de LIKE prendrait généralement plus longtemps que son une correspondance de modèle. Toutefois,

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

et

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

donnerait des résultats différents, où utiliser " = "ne donne que des résultats avec" Chris% "retourné et l'opérateur similaire retournera tout ce qui commence par"Chris".

Espère que ça aide. Quelques bonnes informations peuvent être trouvées ici .

167
répondu achinda99 2009-02-12 22:25:09

LIKE et = sont différents. LIKE est ce que vous utiliseriez dans une requête de recherche. Il permet également les jokers comme _ (simple caractère Joker) et % (multi-caractère Joker).

= doit être utilisé si vous voulez des Correspondances exactes et il sera plus rapide.

ce site explique LIKE

16
répondu WalterJ89 2014-12-08 11:21:50

ceci est une copie / pâte d'une autre de mes réponses à la question SQL 'like' vs ' = 'performance :

un exemple personnel en utilisant mysql 5.5: j'ai eu une jonction interne entre 2 tables, une de 3 millions de lignes et une de 10 000 lignes.

l'utilisation d'un tel dans un index comme ci-dessous(pas de Joker) a pris environ 30 secondes:

where login like '12345678'

à l'aide "d'expliquer" j'obtiens:

enter image description here

quand on utilise un ' = 'sur la même requête, cela prend environ 0.1 secondes:

where login ='12345678'

à l'Aide "d'expliquer" j'obtiens:

enter image description here

comme vous pouvez le voir, le like a complètement annulé la recherche d'index, donc la requête a pris 300 fois plus de temps.

14
répondu Aris 2017-05-23 12:18:24

une différence - en dehors de la possibilité d'utiliser des caractères génériques avec comme - est dans les espaces de fuite: l'opérateur = ignore l'espace de fuite, mais comme ne le fait pas.

11
répondu ISW 2009-02-12 22:03:03

Dépend du système de base de données.

généralement sans caractères spéciaux, oui, = et comme sont les mêmes.

certains systèmes de bases de données, cependant, peuvent traiter les paramètres de collation différemment des différents opérateurs.

par exemple, dans les comparaisons MySQL avec = on strings est toujours insensible à la casse par défaut, donc comme sans caractères spéciaux est le même. Sur d'autres RDBM, le genre est insensible à la casse alors que = est pas.

9
répondu ʞɔıu 2009-02-12 22:59:44

pour cet exemple, nous tenons pour acquis que varcharcol ne contient pas '' et n'a pas de case vide contre cette colonne

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

le premier résultat est 0 ligne de sortie tandis que le second affiche toute la liste. = est strictement respecter la casse, tout comme agit comme un filtre. si le filtre n'a pas de critères, toutes les données sont valides.

comme-par la vertu de son but fonctionne un peu plus lent et est destiné à être utilisé avec varchar et des données similaires.

9
répondu Arnab 2012-11-14 08:50:38

utilisant = évite les caractères génériques et les conflits de caractères spéciaux dans la chaîne lorsque vous construisez la requête au moment de l'exécution.

cela rend la vie du programmeur plus facile en n'ayant pas à échapper à tous les caractères génériques spéciaux qui pourraient glisser dans la clause similaire et de ne pas produire le résultat prévu. Après tout, = 99% scénario de cas d'utilisation, il serait une douleur d'avoir à échapper à chaque fois.

roule des yeux à années '90

je pense aussi que c'est un peu plus lent, mais je doute que ce soit significatif s'il n'y a pas de jokers dans le motif.

6
répondu Coincoin 2009-02-13 16:39:11

pour répondre à la question initiale concernant la performance, il s'agit de utilisation de l'indice . Quand un simple scan de table se produit, "comme" et " = "sont identique . Quand les index sont impliqués, il dépend sur la façon dont la clause similaire est formée. Plus précisément, où se trouve le ou les caractères génériques?


considérer ce qui suit:

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

il peut également y avoir une différence négligeable dans la création du plan de requête en utilisant " = "vs"LIKE".

6
répondu Laramie 2010-04-12 21:09:57

si vous recherchez une correspondance exacte, vous pouvez utiliser les deux, = et LIKE.

utiliser " = "est un tout petit peu plus rapide dans ce cas (recherche d'une correspondance exacte) - vous pouvez vérifier cela vous-même en ayant la même requête deux fois dans SQL Server Management Studio, une fois en utilisant"=", une fois en utilisant" LIKE", puis en utilisant la" requête " / "inclure plan d'exécution réelle".

exécutez les deux requêtes et vous devriez voir vos résultats deux fois, plus les deux plans d'exécution réels. Dans mon cas, ils ont été divisés 50% contre 50%, mais le plan d'exécution "=" a un plus petit "coût estimé sous-trois" (affiché lorsque vous survolez la gauche - plus "Sélectionner" boîte) - mais encore une fois, ce n'est vraiment pas une énorme différence.

mais quand vous commencez à chercher avec des caractères génériques dans votre expression similaire, la performance de recherche va diminuer. La recherche "comme Mill%" peut toujours être très rapide - SQL Server peut utiliser un index sur cette colonne, s'il y en a un. Chercher " LIKE % expression%" est horriblement lent, depuis la seule façon SQL Server peut satisfaire cette recherche est en faisant un balayage complet de la table. Alors faites attention à vos goûts !

Marc

5
répondu marc_s 2009-02-13 06:19:41

outre les caractères génériques, la différence entre = et LIKE dépendra à la fois du type de serveur SQL et du type de colonne.

prendre cet exemple:

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 '
  • en utilisant MS SQL Server 2012 , les espaces de fuite seront ignorés dans la comparaison, sauf avec LIKE lorsque le type de colonne est VARCHAR .

  • en utilisant MySQL 5.5 , les espaces de fuite seront ignorés pour = , mais pas pour LIKE , à la fois avec CHAR et VARCHAR .

  • utilisant PostgreSQL 9.1 , les espaces sont significatifs à la fois avec = et LIKE utilisant VARCHAR , mais pas avec CHAR (voir documentation ).

    le comportement avec LIKE diffère aussi de CHAR .

    en utilisant les mêmes données que ci-dessus, en utilisant un CAST explicite sur le nom de la colonne fait également une différence :

    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)
    

    cela renvoie seulement les lignes pour" CAST both "et"CAST col".

4
répondu Bruno 2012-11-10 22:40:05

le même mot-clé vient sans aucun doute avec une" performance price-tag " attaché. Cela dit, si vous avez un champ d'entrée qui pourrait inclure des caractères wild card à utiliser dans votre requête, je vous recommande D'utiliser comme seulement si l'entrée contient une des cartes wild. Sinon, utilisez la norme égale à la comparaison.

meilleures salutations...

2
répondu Josh Stodola 2009-02-12 22:23:46

en fait, il s'agit de ce que vous voulez que la requête à faire. Si vous voulez dire une correspondance exacte puis utiliser =. Si vous voulez dire un match plus fuzzier, alors utilisez comme. Dire ce que vous entendez est généralement une bonne politique avec le code.

1
répondu notnot 2009-02-12 22:03:09

dans Oracle, un ‘like’ sans joker retournera le même résultat qu'un ‘equals’, mais pourrait nécessiter un traitement supplémentaire. selon Tom Kyte , Oracle traitera un "like" sans caractères génériques comme un "equals" lorsqu'il utilise des caractères littéraux, mais pas lorsqu'il utilise des variables bind.

1
répondu Chris B 2013-06-04 22:13:07

= et LIKE n'est pas le même;

  1. = correspond à la chaîne exacte
  2. LIKE correspond à une chaîne qui peut contenir des caractères génériques ( % )
0
répondu baretta 2015-09-21 06:41:30