Question

Lorsque vous utilisez SQL, sont-il des avantages de l'utilisation = dans une clause de WHERE au lieu de LIKE?

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

Était-ce utile?

La solution

différents opérateurs

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

= est un opérateur de comparaison qui fonctionne sur le nombre et les chaînes. Lorsque l'on compare 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 qui peut avoir des effets importants sur le résultat de la comparaison.

Motivating Exemple

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

  

Par la norme SQL, LIKE fait correspondant à un, ainsi peut produire des résultats différents base par caractère 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 |
+--------------------------------------+

S'il vous plaît noter que cette page du manuel MySQL est appelé Fonctions chaîne de comparaison , et = n'est pas traitée, ce qui implique que = n'est pas strictement une fonction de comparaison de chaînes.

Comment fonctionne = travail?

Le SQL standard § 8.2 décrit comment = compare chaînes:

  

La comparaison des 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 efficacement   remplacé, aux fins de comparaison, une copie de   lui-même qui a été étendue à la longueur de la plus longue   chaîne par concaténation sur le droit d'un ou plusieurs tapis   caractères, où le personnage de tampon est choisi sur la base CS. Si   CS a l'attribut NO PAD, le caractère pad est un   caractère dépendant de l'implémentation différent de tout   caractère dans le jeu de caractères de X et Y qui rassemble moins   que toute chaîne sous CS. Dans le cas contraire, le caractère pad est   .

     

b) reçoit le résultat de la comparaison de X et Y par le   séquence de classement CS.

     

c) En fonction de la séquence de tri, de deux chaînes peut   comme égales, même si elles sont de différentes longueurs ou   contenir des séquences différentes de caractères. Lorsque les opérations   MAX, MIN, DISTINCT, les références à une colonne de regroupement et la   UNION, SAUF, et les opérateurs INTERSECT se réfèrent à caractère   chaînes, la valeur spécifique choisie par ces opérations de   un ensemble de telles valeurs égales est dépendant de l'implémentation.

(soulignement ajouté).

Qu'est-ce que cela signifie? Cela signifie que lorsque l'on compare les chaînes, l'opérateur de = est juste une enveloppe mince autour de la collation en cours. Une collation est une bibliothèque qui a des règles différentes pour la comparaison des chaînes. Voici un exemple de binaire à partir d'une collation 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);
}

Cette collation particulier arrive à comparer octet par octet (ce qui est la raison pour laquelle il est appelé « binaire » - il ne donne aucune signification particulière à cordes). D'autres peuvent fournir des comparaisons des classements plus avancées.

Par exemple, voici un UTF- 8 collation qui prend en charge les comparaisons insensibles à la casse. Le code est trop long pour coller ici, mais aller à ce lien et lire le corps de my_strnncollsp_utf8mb4(). Cette collecte peut traiter plusieurs octets à la fois et il peut appliquer diverses transformations (comme la comparaison de la casse). L'opérateur = est complètement abstraitedes aléas de la collation.

Comment fonctionne LIKE travail?

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

  

Le

     

M LIKE P

     

est vrai s'il existe une partition de M en sous-chaînes   de telle sorte que:

     

i) une sous-chaîne de M est une séquence de 0 ou plus contiguë    s de M et chaque caractère <   représentation> M fait partie d'exactement une sous-chaîne.

     

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

     

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

     

iv) Si le spécificateur substring i-ième place est ni une   spécificateur de caractère arbitraire ni une spécificateur de chaîne arbitraire,   puis la sous-chaîne de la i-ième M est égal à celui sous-chaîne   spécificateur selon l'ordre de classement de   le , sans l'adjonction de   caractères à m, et a la même longueur que celle-chaîne   spécificateur.

     

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

(soulignement ajouté).

est assez verbeux, donc nous allons le décomposer. Articles ii et iii se référer à la wildcards _ et %, respectivement. Si P ne contient pas de caractères génériques, seul point iv applique. Tel est le cas d'intérêt posé par l'OP.

Dans ce cas, il compare chaque « sous-chaîne » (caractères individuels) dans chaque M contre substring en P utilisant le classement actuel.

Conclusions

La ligne de fond 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 utilisent le classement actuel. Cette différence conduit à des résultats différents dans certains cas, comme en témoigne le premier exemple dans ce message.

Lequel devriez-vous utiliser? Personne ne peut vous dire que - vous devez utiliser celui qui est correct pour votre cas d'utilisation. Ne pas prématurément optimiser par commutation des opérateurs de comparaison.

Autres conseils

l'opérateur égal (=) est un « opérateur de comparaison compare deux valeurs pour l'égalité. » En d'autres termes, dans une instruction SQL, il ne reviendra pas vrai que si les deux côtés de l'équation sont égales. Par exemple:

SELECT * FROM Store WHERE Quantity = 200;

L'opérateur LIKE « met en oeuvre une comparaison de correspondance de motif » qui tente de faire correspondre « une valeur de chaîne contre une chaîne de motif contenant des caractères génériques. » Par exemple:

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

LIKE est généralement utilisé avec des chaînes et égaux (je crois) est plus rapide. Egaux traite l'opérateur des caractères génériques comme des caractères. La différence dans les résultats retournés sont les suivants:

SELECT * FROM Employees WHERE Name = 'Chris';

SELECT * FROM Employees WHERE Name LIKE 'Chris';

renverrait le même résultat, bien que l'utilisation prendrait généralement COMME plus comme un match de modèle. Cependant,

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

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

Nous y retournerions des résultats différents, où l'utilisation « = » résultats en résultats avec seulement « Chris% » son retour et l'opérateur LIKE retournera quoi que ce soit en commençant par « Chris ».

L'espoir qui aide. Quelques bonnes informations sont disponibles .

LIKE et = sont différents. LIKE est ce que vous utilisez dans une requête de recherche. Il permet également des jokers comme _ (générique de caractères simples) et % (caractère générique à plusieurs caractères).

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

Ce site explique LIKE

Ceci est un copier / coller d'une autre réponse à moi pour la question SQL « comme » vs performance de = ':

Un exemple personnel en utilisant MySQL 5.5: J'ai eu une jointure interne entre 2 tables, l'un des 3 millions de lignes et un de 10 mille lignes

.

Lorsque vous utilisez un comme sur un indice comme ci-dessous (pas de caractères génériques), il a fallu environ 30 secondes:

where login like '12345678'

à l'aide 'expliquer' je reçois:

entrer image description ici

Lorsque vous utilisez un « = » sur la même requête, il a fallu environ 0,1 secondes:

where login ='12345678'

Utilisation 'expliquer' je reçois:

entrer image description ici

Comme vous pouvez le voir, le like complètement annulé l'index chercher, si la requête a pris 300 fois plus de temps.

.

Une différence - à part la possibilité d'utiliser des jokers avec LIKE - est dans les espaces de fin: L'opérateur = ignore l'espace de fuite, mais comme ne pas

Cela dépend du système de base de données.

En général, sans caractères spéciaux, oui, = et similaires sont les mêmes.

Certains systèmes de base de données, cependant, peut traiter différemment les paramètres de classement avec les différents opérateurs.

Par exemple, dans les comparaisons avec MySQL = sur les chaînes est toujours insensible à la casse par défaut, sans caractères spéciaux COMME est le même. Sur un autre LIKE SGBDR est insensible à la casse alors que = est pas.

Pour cet exemple, nous prenons pour acquis que varcharcol ne contient pas '' et ont aucune cellule vide contre cette colonne

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

Le premier résultat en sortie 0 de la rangée tandis que le second indique la liste entière. = Est le cas strictement match 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 objet fonctionne un peu plus lent et est destiné à être utilisé avec des données varchar et similaires

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

Utilisation « = » est un petit peu plus rapide dans ce cas (la recherche d'une correspondance exacte) - vous pouvez 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 », puis en utilisant la « requête »/ « Inclure le plan d'exécution réelle ».

Exécuter les deux requêtes et vous devriez voir vos résultats deux fois, ainsi que les deux plans d'exécution réels. Dans mon cas, ils ont été divisés 50% par rapport à 50%, mais le « = » plan d'exécution a un plus petit « coût de sous-arbre estimé » (affiché lorsque vous passez la souris sur la gauche case la plus « SELECT ») - mais encore une fois, il est vraiment pas une énorme différence.

Mais quand vous commencez la recherche avec des caractères génériques dans votre expression LIKE, les performances de recherche sera dimish. Recherche « LIKE Mill% » peut encore être assez rapide - SQL Server peut utiliser un index sur cette colonne, si elle existe. Recherche « LIKE%% d'expression » est horriblement lent, car la seule façon SQL Server peut satisfaire cette recherche est en faisant une analyse complète de la table. Faites donc attention à votre goût de!

Marc

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

Cela rend plus facile par la vie du programmeur ne pas avoir à tous les caractères génériques spéciaux qui pourraient se glisser dans la clause LIKE et qui ne produisent pas le résultat escompté. Après tout, = est le scénario de cas d'utilisation de 99%, ce serait une douleur d'avoir à leur échapper chaque fois.

roule les yeux à des années 90

Je pense aussi qu'il est un peu plus lent, mais je doute qu'il est important s'il n'y a pas de caractères génériques dans le motif.

Pour répondre à la question initiale en ce qui concerne la performance, il se résume à l'utilisation de l'indice . Lorsqu'une analyse simple de la table se produit, "LIKE" et "=" sont identiques . Lorsque les index sont impliqués, il dépend sur la façon dont la clause LIKE est formée. Plus précisément, quel est l'emplacement du caractère générique (s)?


Considérez 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 y avoir aussi la différence négligeable dans la création du plan de requête lors de l'utilisation « = » vs « LIKE ».

En plus des caractères génériques, la différence entre = ET LIKE dépendra à la fois du type de serveur SQL et sur le type de colonne.

Prenez 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 '
  • MS SQL Server 2012 , les espaces de fin seront ignorées dans la comparaison, à l'exception de LIKE lorsque le type de colonne est VARCHAR.

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

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

    Le comportement avec LIKE diffère également CHAR.

    En utilisant les mêmes données ci-dessus, au moyen d'un CAST explicite sur le nom de colonne fait aussi 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)
    

    Ce ne retourne que les lignes pour "CAST fois" et "CAST col".

Le mot-clé LIKE est sans aucun doute avec un « prix-étiquette de performance » ci-joint. Cela dit, si vous avez un champ de saisie qui pourrait éventuellement inclure des caractères génériques à utiliser dans votre requête, je vous conseille d'utiliser comme uniquement si l'entrée contient l'une des cartes sauvages. Dans le cas contraire, utilisez la norme égale à la comparaison.

Cordialement ...

En réalité, il se résume à ce que vous voulez que la requête fasse. Si vous voulez dire une correspondance exacte puis utilisez =. Si vous voulez dire un match plus floue, utilisez LIKE. Dire ce que vous entendez est généralement une bonne politique avec le code.

Dans Oracle, un « comme » sans jokers retournera le même résultat comme un « égal », mais pourrait nécessiter un traitement supplémentaire. Selon Tom Kyte , Oracle traitera un « comme » sans jokers comme « égaux » lors de l'utilisation littéraux, mais pas lors de l'utilisation des variables de liaison.

= et LIKE ne sont pas les mêmes;

  1. = correspond exactement à la chaîne
  2. LIKE correspond à une chaîne qui peut contenir des caractères génériques (%)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top