Diferentes operadores
LIKE
y =
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 .
LIKE
es 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 LIKE
trabajo?
El Estándar SQL § 8.5 describe cómo LIKE
compara 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 P
no 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 M
cada subcadena al P
usar la colación actual.
Conclusiones
La conclusión es que al comparar cadenas, =
compara toda la cadena mientras LIKE
compara 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.