Igual (=) vs. ME GUSTA

282

Al usar SQL, ¿hay algún beneficio de usar =en una WHEREcláusula en lugar de LIKE?

Sin ningún operador especial, LIKEy =son lo mismo, ¿verdad?

Travis
fuente
44
¿Podría querer especificar un tipo de base de datos ... mssql, mysql, oracle?
Allen Rice
1
Su pregunta tiene al menos 5votos para la etiqueta de operador similar . ¿Podría solicitar amablemente que sugiera sql-like como sinónimo ?
Kermit
@FreshPrinceOfSO, lo haré cuando tenga suficiente reputación. Gracias.
Travis

Respuestas:

271

Diferentes operadores

LIKEy =son diferentes operadores. ¡La mayoría de las respuestas aquí se centran en el soporte de comodines, que no es la única diferencia entre estos operadores!

=es un operador de comparación que opera con números y cadenas. Al comparar cadenas, el operador de comparación compara cadenas enteras .

LIKEes un operador de cadena que compara carácter por carácter .

Para complicar las cosas, ambos operadores usan una clasificación que puede tener efectos importantes en el resultado de la comparación.

Ejemplo motivador

Primero identifiquemos un ejemplo donde estos operadores producen resultados obviamente diferentes. Permítanme citar el manual de MySQL:

Según el estándar SQL, LIKE realiza la coincidencia por carácter, por lo que puede producir resultados diferentes del operador de comparación =:

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

Tenga en cuenta que esta página del manual de MySQL se llama Funciones de comparación de cadenas y =no se trata, lo que implica que =no es estrictamente una función de comparación de cadenas.

¿Cómo funciona el =trabajo?

El Estándar SQL § 8.2 describe cómo =compara cadenas:

La comparación de dos cadenas de caracteres se determina de la siguiente manera:

a) Si la longitud en caracteres de X no es igual a la longitud en caracteres de Y, entonces la cadena más corta se reemplaza efectivamente, para fines de comparación, con una copia de sí misma que se ha extendido a la longitud de la cadena más larga por concatenación a la derecha de uno o más caracteres del pad, donde el carácter del pad se elige en base a CS. Si CS tiene el atributo NO PAD, entonces el carácter del pad es un carácter dependiente de la implementación diferente de cualquier carácter en el conjunto de caracteres de X e Y que clasifica menos que cualquier cadena en CS. De lo contrario, el carácter del pad es a.

b) El resultado de la comparación de X e Y viene dado por la secuencia de clasificación CS.

c) Dependiendo de la secuencia de clasificación, dos cadenas pueden compararse como iguales incluso si son de diferentes longitudes o contienen diferentes secuencias de caracteres. Cuando las operaciones MAX, MIN, DISTINCT, las referencias a una columna de agrupación y los operadores UNION, EXCEPT e INTERSECT se refieren a cadenas de caracteres, el valor específico seleccionado por estas operaciones de un conjunto de valores iguales depende de la implementación.

(Énfasis añadido.)

¿Qué significa esto? Significa que al comparar cadenas, el =operador es solo una delgada envoltura alrededor de la clasificación actual. Una clasificación es una biblioteca que tiene varias reglas para comparar cadenas. Aquí hay un ejemplo de una colación binaria 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);
}

Esta colación particular se compara para comparar byte por byte (por eso se llama "binario", no le da ningún significado especial a las cadenas). Otras colaciones pueden proporcionar comparaciones más avanzadas.

Por ejemplo, aquí hay una clasificación UTF-8 que admite comparaciones que no distinguen entre mayúsculas y minúsculas. El código es demasiado largo para pegar aquí, pero vaya a ese enlace y lea el cuerpo de my_strnncollsp_utf8mb4(). Esta intercalación puede procesar varios bytes a la vez y puede aplicar varias transformaciones (como la comparación entre mayúsculas y minúsculas). El =operador está completamente abstraído de los caprichos de la colación.

¿Cómo funciona el LIKEtrabajo?

El Estándar SQL § 8.5 describe cómo LIKEcompara cadenas:

El <predicar>

M LIKE P

es cierto si existe una partición de M en subcadenas de manera que:

i) Una subcadena de M es una secuencia de 0 o más <representación de caracteres> s contigua de M y cada <representación de caracteres> de M es parte de exactamente una subcadena.

ii) Si el especificador de subcadena i-ésima de P es un especificador de caracteres arbitrario, la subcadena i-ésima de M es cualquier <representación de carácter> individual.

iii) Si el especificador de subcadena i-ésima de P es un especificador de cadena arbitraria, entonces la subcadena i-ésima de M es cualquier secuencia de 0 o más <representación de caracteres> s.

iv) Si el especificador de subcadena i-ésima de P no es un especificador de caracteres arbitrario ni un especificador de cadena arbitrario, entonces la subcadena i-ésima de M es igual a ese especificador de subcadena de acuerdo con la secuencia de clasificación del <predicado similar>, sin la adición de caracteres <space> a M, y tiene la misma longitud que ese especificador de subcadena.

v) El número de subcadenas de M es igual al número de especificadores de subcadena de P.

(Énfasis añadido.)

Esto es bastante prolijo, así que analicemos. Los ítems ii y iii se refieren a los comodines _y %, respectivamente. Si Pno contiene comodines, solo se aplica el elemento iv. Este es el caso de interés planteado por el OP.

En este caso, compara cada "subcadena" (caracteres individuales) con Mcada subcadena al Pusar la colación actual.

Conclusiones

La conclusión es que al comparar cadenas, =compara toda la cadena mientras LIKEcompara un carácter a la vez. Ambas comparaciones usan la colación actual. Esta diferencia conduce a resultados diferentes en algunos casos, como se evidencia en el primer ejemplo en esta publicación.

¿Cual deberías usar? Nadie puede decirte eso: debes usar el que sea correcto para tu caso de uso. No optimice prematuramente cambiando operadores de comparación.

Mark E. Haase
fuente
44
"EQUALS compara dos piezas de datos byte a byte": simplificado en exceso, y con demasiada frecuencia no es cierto, porque el comportamiento EQUALS (=) se puede modificar con COLLATE, lo que hace que se comparen las clases de caracteres en lugar de los caracteres. Por ejemplo, vea dev.mysql.com/doc/refman/5.0/en/charset-collate.html (MySQL) o sqlmag.com/blog/forcing-collation-where-clause-22-jun-2011 (SQL Server).
Peter B
11
Esta es la respuesta correcta. Sabemos lo que LIKEhace, pero esta respuesta explica asombrosamente que usar LIKEsin %o _presente no es lo mismo que usar =. Que tu respuesta reciba mil votos a favor.
rinogo
1
@mehase esto no puede ser cierto. Si mi campo varchar contiene el valor 'AbCdEfG', y lo hago WHERE MyCol = 'abcdefg', todavía recupero esa fila, a pesar de que claramente no son equivalentes byte a byte
Kip
1
PeterB y @Kip plantean buenos puntos. He mejorado mi respuesta para tratar de explicar cómo la colación afecta a estos operadores.
Mark E. Haase
2
Esto ya no parece cierto: set charset latin1; SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;da 0 y también SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;da 0.
joanq
170

El operador igual (=) es un "operador de comparación compara dos valores para la igualdad". En otras palabras, en una declaración SQL, no devolverá verdadero a menos que ambos lados de la ecuación sean iguales. Por ejemplo:

SELECT * FROM Store WHERE Quantity = 200;

El operador LIKE "implementa una comparación de coincidencia de patrón" que intenta hacer coincidir "un valor de cadena con una cadena de patrón que contiene caracteres comodín". Por ejemplo:

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

LIKE generalmente se usa solo con cadenas e iguales (creo) es más rápido. El operador igual trata los caracteres comodín como caracteres literales. La diferencia en los resultados devueltos son los siguientes:

SELECT * FROM Employees WHERE Name = 'Chris';

Y

SELECT * FROM Employees WHERE Name LIKE 'Chris';

Devolvería el mismo resultado, aunque usar LIKE generalmente llevaría más tiempo ya que es una coincidencia de patrón. Sin embargo,

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

Y

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

Devuelve resultados diferentes, donde el uso de "=" da como resultado solo resultados con "Chris%" y el operador LIKE devolverá cualquier cosa que comience con "Chris".

Espero que ayude. Alguna buena información se puede encontrar aquí .

achinda99
fuente
108
Tengo la impresión de que el OP sabe cuándo usar LIKE y cuándo usar =, solo se pregunta si hay una diferencia de rendimiento cuando no hay un comodín presente. Esta respuesta toca brevemente esto, pero siento que el 95% de esta respuesta no es realmente relevante.
Programador fuera de la ley
1
Muy cierto. No estoy seguro de si la pregunta fue la misma cuando la respondí. Si fue así, me perdí la parte que preguntaba sobre la actuación. Gracias por la observación
achinda99
9
Esta respuesta es terrible. LIKE y '=' son operadores completamente distintos, pero se comportan de manera similar en un pequeño subconjunto de casos. En aras de la posteridad, lea el resto de las respuestas aquí, o al menos google para "mysql like" antes de guardar esto en la memoria.
Mark E. Haase
3
Por otro lado, esta respuesta respondió la pregunta que tenía y busqué en Google. A veces es tan bueno si una respuesta responde el título de una pregunta como el contenido.
CorayThan
Una buena idea para recordar es cuando estás usando char y varchar2. Si comparas char con char. Antes de comparar la base de datos, primero convierta la longitud de la primera 'variable' a la misma de la segunda. Si compara char y varchar2, la base de datos no hará nada. docs.oracle.com/cd/A64702_01/doc/server.805/a58236/c_char.htm
xild
18

Esta es una copia / pegar de otra respuesta mía para la pregunta SQL 'like' vs '=' performance :

Un ejemplo personal con mysql 5.5: tenía una unión interna entre 2 tablas, una de 3 millones de filas y una de 10 mil filas.

Al usar un Me gusta en un índice como se muestra a continuación (sin comodines), tardó unos 30 segundos:

where login like '12345678'

usando 'explicar' obtengo:

ingrese la descripción de la imagen aquí

Al usar un '=' en la misma consulta, tardó aproximadamente 0.1 segundos:

where login ='12345678'

Usando 'explicar' obtengo:

ingrese la descripción de la imagen aquí

Como puede ver, likecanceló por completo la búsqueda de índice, por lo que la consulta tomó 300 veces más tiempo.

Aris
fuente
17

LIKEy =son diferentes LIKEes lo que usarías en una consulta de búsqueda. También permite comodines como _(comodín de carácter simple) y %(comodín de varios caracteres).

= debe usarse si desea coincidencias exactas y será más rápido.

Este sitio explica LIKE

WalterJ89
fuente
11

Una diferencia, aparte de la posibilidad de usar comodines con LIKE, está en los espacios finales: El operador = ignora el espacio final, pero LIKE no.

ISW
fuente
44
Si bien esto es cierto para MySQL y MS SQL, esto no es para PostgreSQL.
Bruno
10

Depende del sistema de base de datos.

Generalmente sin caracteres especiales, sí, = y LIKE son iguales.

Sin embargo, algunos sistemas de bases de datos pueden tratar la configuración de intercalación de manera diferente con los diferentes operadores.

Por ejemplo, en MySQL, las comparaciones con = en cadenas siempre distinguen entre mayúsculas y minúsculas, por lo que LIKE sin caracteres especiales es lo mismo. En algunos otros RDBMS, LIKE distingue entre mayúsculas y minúsculas, mientras que = no lo es.

ʞɔıu
fuente
¿Hay algo así como una descripción general de esta rareza?
Gumbo
9

Para este ejemplo, damos por sentado que varcharcol no contiene ''y no tiene una celda vacía en esta columna

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

El primero da como resultado una salida de 0 filas, mientras que el segundo muestra la lista completa. = es un caso estrictamente coincidente, mientras que like actúa como un filtro. Si el filtro no tiene criterios, todos los datos son válidos.

Me gusta: en virtud de su propósito, funciona un poco más lento y está diseñado para usarse con varchar y datos similares.

Arnab
fuente
6

Si busca una coincidencia exacta, puede usar ambos, = y LIKE.

El uso de "=" es un poco más rápido en este caso (buscando una coincidencia exacta): puede verificarlo usted mismo haciendo la misma consulta dos veces en SQL Server Management Studio, una vez usando "=", una vez usando "LIKE", y luego usando "Consulta" / "Incluir plan de ejecución real".

Ejecute las dos consultas y debería ver sus resultados dos veces, más los dos planes de ejecución reales. En mi caso, se dividieron en un 50% frente a un 50%, pero el plan de ejecución "=" tiene un "costo de subárbol estimado" más pequeño (se muestra al pasar el cursor sobre el cuadro "SELECCIONAR" más a la izquierda), pero de nuevo, es realmente No es una gran diferencia.

Pero cuando comienza a buscar con comodines en su expresión LIKE, el rendimiento de la búsqueda disminuirá. La búsqueda "LIKE Mill%" aún puede ser bastante rápida: SQL Server puede usar un índice en esa columna, si hay uno. La búsqueda de "LIKE% expression%" es terriblemente lenta, ya que la única forma en que SQL Server puede satisfacer esta búsqueda es haciendo un escaneo completo de la tabla. ¡Así que ten cuidado con tus LIKE!

Bagazo

marc_s
fuente
-1 como no, no siempre es un poco más rápido. Si la columna se indexa con% mystring%, es un par de órdenes de magnitud más lenta. De hecho, cualquier estándar de código que valga la pena tendrá pautas rigurosas sobre cuándo y cuándo no usar como en una base de datos de mouse más grande que Micky.
Cruachan
1
Nunca dije que sería un poco más lento para todos los casos; dije que sería un poco más lento si busca una coincidencia EXACTA. Por supuesto, buscar con un LIKE y usar comodines, especialmente al principio y al final de su elemento de búsqueda, es MUCHO más lento, de eso no hay duda.
marc_s
Y sí, estoy de acuerdo: uno debe tener pautas claras sobre cuándo usar LIKE o no (solo cuando NECESITA buscar con comodines). Pero, de nuevo - en teoría, no hay diferencia entre la teoría y la práctica, pero en la práctica .......
marc_s
6

El uso de = evita los comodines y los conflictos de caracteres especiales en la cadena cuando genera la consulta en tiempo de ejecución.

Esto facilita la vida del programador al no tener que escapar de todos los caracteres comodín especiales que pueden entrar en la cláusula LIKE y no producir el resultado deseado. Después de todo, = es el escenario de caso de uso del 99%, sería un dolor tener que escapar de ellos cada vez.

pone los ojos en blanco en los años 90

También sospecho que es un poco más lento, pero dudo que sea significativo si no hay comodines en el patrón.

Coincoin
fuente
6

Para abordar la pregunta original sobre el rendimiento, todo se reduce a la utilización del índice . Cuando se produce un escaneo de tabla simple, "LIKE" y "=" son idénticos . Cuando los índices están involucrados, depende de cómo se forme la cláusula LIKE. Más específicamente, ¿cuál es la ubicación de los comodines?


Considera lo siguiente:

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

También puede haber una diferencia insignificante en la creación del plan de consulta al usar "=" vs "LIKE".

Laramie
fuente
4

Además de los comodines, la diferencia entre =AND LIKEdependerá tanto del tipo de servidor SQL como del tipo de columna.

Toma este ejemplo:

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 '
  • Con MS SQL Server 2012 , los espacios finales se ignorarán en la comparación, excepto LIKEcuando el tipo de columna sea VARCHAR.

  • Usando MySQL 5.5 , los espacios finales se ignorarán para =, pero no para LIKE, con CHARy VARCHAR.

  • Usando PostgreSQL 9.1 , los espacios son significativos con ambos =y con el LIKEuso VARCHAR, pero no con CHAR(ver documentación ).

    El comportamiento con LIKEtambién difiere con CHAR.

    Usando los mismos datos que arriba, usando un explícito CASTen el nombre de la columna también hace una diferencia :

    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)

    Esto solo devuelve filas para "CAST both" y "CAST col".

Bruno
fuente
2

La palabra clave LIKE indudablemente viene con una "etiqueta de precio de rendimiento" adjunta. Dicho esto, si tiene un campo de entrada que podría incluir caracteres comodín para su consulta, recomendaría usar LIKE solo si la entrada contiene uno de los comodines. De lo contrario, use el estándar igual a comparación.

Atentamente...

Josh Stodola
fuente
1

Realmente se trata de lo que quieres que haga la consulta. Si quiere decir una coincidencia exacta, use =. Si te refieres a un partido más difuso, usa LIKE. Decir lo que quieres decir suele ser una buena política con el código.

notnot
fuente
1

En Oracle, un 'me gusta' sin comodines devolverá el mismo resultado que un 'igual', pero podría requerir un procesamiento adicional. Según Tom Kyte , Oracle tratará un 'me gusta' sin comodines como un 'igual' cuando use literales, pero no cuando use variables de enlace.

Chris B
fuente
0

=y LIKEno es lo mismo;

  1. = coincide con la cadena exacta
  2. LIKE coincide con una cadena que puede contener comodines (%)
baretta
fuente
2
Respuesta insuficiente
Podría usarse sin comodines. La pregunta planteó la diferencia para los mismos casos.
M-Razavi