Equals (=) vs. LIKE

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

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

Différents opérateurs

LIKE et = sont des opérateurs différents. La plupart des réponses concernent le support des caractères génériques, ce qui n’est pas la seule différence entre ces opérateurs!

= est un opérateur de comparaison qui opère sur des nombres et des chaînes. Lors de la comparaison de chaînes, l’opérateur de comparaison compare des 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 classement qui peut avoir des effets importants sur le résultat de la comparaison.

Exemple de motivation

Identifions d’abord un exemple où ces opérateurs produisent des résultats évidemment différents. Permettez-moi de citer le manuel MySQL:

Selon le standard SQL, LIKE effectue la correspondance pour chaque caractère, ce qui permet d’obtenir des résultats différents de ceux 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 s’appelle Fonctions de comparaison de chaînes , et que = n’est pas discuté, ce qui implique que = n’est pas ssortingctement une fonction de comparaison de chaînes.

Comment ça marche?

Le SQL Standard § 8.2 décrit comment = comparer 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 en caractères de Y, la chaîne la plus courte est effectivement remplacée, à des fins de comparaison, par une copie de lui-même étendue à la longueur de la chaîne la plus longue par concaténation à droite d’un ou plusieurs caractères de pad, où le caractère pad est choisi sur la base de CS. Si CS possède l’atsortingbut NO PAD, le caractère pad est un caractère dépendant de l’implémentation, différent de tout caractère du jeu de caractères X et Y, qui comstack moins que n’importe quelle chaîne sous CS. Sinon, le caractère pad est un.

b) Le résultat de la comparaison de X et Y est donné par la séquence d’assemblage CS.

c) Selon la séquence de classement, deux chaînes peuvent être égales, même si elles ont des longueurs différentes ou contiennent des séquences de caractères différentes. Lorsque les opérations MAX, MIN, DISTINCT, les références à une colonne de regroupement et les opérateurs UNION, EXCEPT et INTERSECT font référence à des chaînes de caractères, la valeur spécifique sélectionnée par ces opérations à partir d’un ensemble de valeurs égales dépend de l’implémentation.

(Accentuation ajoutée.)

Qu’est-ce que ça veut dire? Cela signifie que lorsque vous comparez des chaînes, l’opérateur = est juste une enveloppe mince autour du classement actuel. Un classement est une bibliothèque comportant différentes règles de comparaison de chaînes. Voici un exemple de classement binary de MySQL :

 static int my_strnncoll_binary(const CHARSET_INFO *cs __atsortingbute__((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); } 

Cette collation particulière arrive à comparer octet par octet (c’est pourquoi il est appelé “binary” – il ne donne aucune signification particulière aux chaînes). D’autres classements peuvent fournir des comparaisons plus avancées.

Par exemple, voici un classement UTF-8 qui prend en charge les comparaisons insensibles à la casse. Le code est trop long pour être collé ici, mais allez sur ce lien et lisez le corps de my_strnncollsp_utf8mb4() . Ce classement peut traiter plusieurs octets à la fois et peut appliquer diverses transformations (telles que la comparaison insensible à la casse). L’opérateur = est complètement extrait des aléas du classement.

Comment ça LIKE ?

Le standard SQL § 8.5 décrit comment LIKE compare les chaînes:

Le

M LIKE P

est vrai s’il existe un partitionnement de M en sous-chaînes telles que:

i) Une sous-chaîne de M est une séquence de 0 ou plus contiguës de M et chaque de M fait partie d’une sous-chaîne.

ii) Si le spécificateur de sous-chaîne i-ième de P est un spécificateur de caractère arbitraire, la i-ième sous-chaîne de M est une seule .

iii) Si le spécificateur de sous-chaîne i-ième de P est un spécificateur de chaîne arbitraire, la i-ème sous-chaîne de M est une séquence de 0 ou plus s.

iv) Si le spécificateur de sous-chaîne i-ième de P n’est ni un spécificateur de caractère arbitraire ni un spécificateur de chaîne arbitraire, la i-ième sous-chaîne de M est égale à ce spécificateur de sous-chaîne selon la séquence de classement du prédicat à M et la même longueur que le spécificateur de sous-chaîne.

v) Le nombre de sous-chaînes de M est égal au nombre de spécificateurs de sous-chaîne de P.

(Accentuation ajoutée.)

Ceci est assez verbeux, alors nous allons le décomposer. Les éléments ii et iii se réfèrent respectivement aux caractères génériques _ et % . Si P ne contient aucun caractère générique, seul l’élément iv s’applique. C’est le cas d’intérêt posé par le PO.

Dans ce cas, il compare chaque “sous-chaîne” (caractères individuels) en M à chaque sous-chaîne en P utilisant le classement actuel.

Conclusions

La ligne du bas est que lors de la comparaison de chaînes, = compare la chaîne entière alors que LIKE compare un caractère à la fois. Les deux comparaisons utilisent le classement actuel. Cette différence conduit à des résultats différents dans certains cas, comme le montre le premier exemple de cet article.

Lequel devriez-vous utiliser? Personne ne peut vous dire cela – vous devez utiliser celui qui convient à votre cas d’utilisation. Ne pas optimiser prématurément en changeant d’opérateurs de comparaison.

L’opérateur égal à (=) est un “opérateur de comparaison compare deux valeurs pour l’égalité”. En d’autres termes, dans une instruction SQL, elle ne retournera pas true à moins que les deux côtés de l’équation soient égaux. Par exemple:

 SELECT * FROM Store WHERE Quantity = 200; 

L’opérateur LIKE “implémente une comparaison de correspondance de modèle” qui tente de faire correspondre “une valeur de chaîne à une chaîne de modèle contenant des caractères génériques”. Par exemple:

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

LIKE est généralement utilisé uniquement avec des chaînes et est égal (je crois) plus rapide. L’opérateur égal traite les caractères génériques comme des caractères littéraux. La différence entre les résultats renvoyés est la suivante:

 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 prenne généralement plus de temps car il correspond à un motif. cependant,

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

Et

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

Renvoyer des résultats différents, où l’utilisation de “=” ne donne que des résultats avec “Chris%” renvoyé et l’opérateur LIKE renverra tout ce qui commence par “Chris”.

J’espère que cela pourra aider. Quelques bonnes informations peuvent être trouvées ici .

LIKE et = sont différents. LIKE est ce que vous utiliseriez dans une requête de recherche. Il autorise également les caractères génériques tels que _ (caractère générique simple) et % (caractère générique multi-caractères).

= devrait être utilisé si vous voulez des correspondances exactes et ce sera plus rapide.

Ce site explique LIKE

Ceci est un copier / coller d’une autre de mes réponses pour la question SQL ‘comme’ vs ‘=’ performance :

Un exemple personnel avec mysql 5.5: j’avais une jointure interne entre 2 tables, l’une des 3 millions de lignes et l’une des 10 mille lignes.

Lorsque vous utilisez un like sur un index comme ci-dessous (pas de joker), cela prend environ 30 secondes:

 where login like '12345678' 

en utilisant «expliquer» je reçois:

entrer la description de l'image ici

En utilisant un ‘=’ sur la même requête, il a fallu environ 0,1 seconde:

 where login ='12345678' 

En utilisant «Expliquer», j’obtiens:

entrer la description de l'image ici

Comme vous pouvez le voir, le like complètement annulé la recherche d’index, donc l’interrogation a pris 300 fois plus de temps.

Une différence – hormis la possibilité d’utiliser des caractères génériques avec LIKE – réside dans les espaces de fin: L’opérateur = ignore les espaces de fin, mais LIKE ne le fait pas.

Dépend du système de firebase database.

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

Certains systèmes de bases de données peuvent toutefois traiter les parameters de classement différemment avec les différents opérateurs.

Par exemple, dans MySQL, les comparaisons avec = on ssortingngs sont toujours insensibles à la casse par défaut, donc LIKE sans caractères spéciaux est identique. Sur certains autres SGBDR, LIKE est insensible à la casse alors que = ne l’est pas.

Pour cet exemple, nous considérons que varcharcol ne contient pas de '' et n’a pas de cellule vide dans cette colonne.

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

Le premier produit 0 sortie de ligne alors que le second affiche la liste complète. = correspond ssortingctement à la casse alors que like agit comme un filtre. si le filtre n’a pas de critère, chaque donnée est valide.

like – en vertu de son objective fonctionne un peu plus lentement et est destiné à être utilisé avec varchar et des données similaires.

L’utilisation de = évite les caractères génériques et les conflits de caractères spéciaux dans la chaîne lorsque vous créez la requête au moment de l’exécution.

Cela simplifie la vie du programmeur en évitant d’échapper à tous les caractères génériques spéciaux susceptibles de glisser dans la clause LIKE et de ne pas produire le résultat souhaité. Après tout, le scénario de cas d’utilisation de 99%, ce serait pénible de devoir y échapper à chaque fois.

roule des yeux aux 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 joker dans le motif.

Pour répondre à la question initiale concernant les performances, il s’agit de l’ utilisation des index . Lorsqu’un simple scan de table se produit, “LIKE” et “=” sont identiques . Lorsque des index sont impliqués, cela dépend de la façon dont la clause LIKE est formée. Plus précisément, quel est l’emplacement des 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 lors de l’utilisation de “=” vs “LIKE”.

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

Utiliser “=” est un peu plus rapide dans ce cas (rechercher une correspondance exacte) – vous pouvez le vérifier 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”, et puis en utilisant le “Query” / “Inclure le plan d’exécution réel”.

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 “coût estimé du sous-arbre” plus petit (affiché lorsque vous survolez la case “SELECT” la plus à gauche). pas une énorme différence.

Mais lorsque vous commencez à chercher avec des caractères génériques dans votre expression LIKE, les performances de recherche diminuent. La recherche “LIKE Mill%” peut encore être assez rapide – SQL Server peut utiliser un index sur cette colonne, le cas échéant. La recherche de “LIKE% expression%” est terriblement lente, car la seule façon dont SQL Server peut satisfaire cette recherche est d’effectuer une parsing complète de la table. Alors faites attention à vos LIKE!

Marc

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

Prenons 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 ' 
  • À l’aide de MS SQL Server 2012 , les espaces de fin seront ignorés dans la comparaison, sauf avec LIKE lorsque le type de colonne est VARCHAR .

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

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

    Le comportement avec LIKE diffère également avec CHAR .

    En utilisant les mêmes données que ci-dessus, l’utilisation d’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 ne renvoie que les lignes pour “CAST deux” et “CAST col”.

Le mot clé LIKE est sans aucun doute associé à un “prix-étiquette de performance”. Cela dit, si vous avez un champ de saisie pouvant éventuellement inclure des caractères génériques à utiliser dans votre requête, je vous recommande d’utiliser LIKE uniquement si l’entrée contient l’un des caractères génériques. Sinon, utilisez la norme égale à la comparaison.

Meilleures salutations…

Cela dépend vraiment de ce que vous voulez que la requête fasse. Si vous voulez dire une correspondance exacte, utilisez =. Si vous voulez dire une correspondance plus floue, utilisez LIKE. Dire ce que vous voulez dire est généralement une bonne politique avec le code.

Dans Oracle, un “like” sans caractères génériques renverra le même résultat qu’un “égal”, mais pourrait nécessiter un traitement supplémentaire. Selon Tom Kyte , Oracle traitera un «similaire» sans caractères génériques comme «égal» lors de l’utilisation de littéraux, mais pas lors de l’utilisation de variables liées.

= et LIKE n’est pas la même chose;

  1. = correspond à la chaîne exacte
  2. LIKE correspond à une chaîne pouvant contenir des caractères génériques (%)