Recibo el siguiente error al intentar hacer una selección a través de un procedimiento almacenado en MySQL.
Mezcla ilegal de intercalaciones (latin1_general_cs, IMPLICIT) y (latin1_general_ci, IMPLICIT) para la operación '='
¿Alguna idea de lo que podría estar yendo mal aquí?
La clasificación de la tabla es latin1_general_ci
y la de la columna en la cláusula where latin1_general_cs
.
Respuestas:
En general, esto se debe al comparar dos cadenas de clasificación incompatibles o al intentar seleccionar datos de clasificación diferente en una columna combinada.
La cláusula le
COLLATE
permite especificar la clasificación utilizada en la consulta.Por ejemplo, la siguiente
WHERE
cláusula siempre dará el error que publicó:Su solución es especificar una intercalación compartida para las dos columnas dentro de la consulta. Aquí hay un ejemplo que usa la
COLLATE
cláusula:Otra opción es usar el
BINARY
operador:Su solución podría verse más o menos así:
o,
fuente
COLLATE latin1_general_ci
que causa otro error: ¡COLLATION 'utf8_general_ci' is not valid for CHARACTER SET 'latin1''
incluso si no tiene una columna con CHARACTER SET 'latin1'! La solución es usar el molde BINARIO. Ver también esta preguntaTL; DR
Cambie la intercalación de una (o ambas) cadenas para que coincidan o agregue una
COLLATE
cláusula a su expresión.¿Qué es esta cosa de "colación" de todos modos?
Como se documenta en Conjuntos de caracteres y colaciones en general :
Se dan ejemplos adicionales en Ejemplos del efecto de la colación .
Bien, pero ¿cómo decide MySQL qué intercalación usar para una expresión dada?
Como se documenta en Colación de expresiones :
Entonces, ¿qué es una "mezcla ilegal de colaciones"?
Una "mezcla ilegal de colaciones" ocurre cuando una expresión compara dos cadenas de colaciones diferentes pero de igual coercibilidad y las reglas de coercibilidad no pueden ayudar a resolver el conflicto. Es la situación descrita bajo el tercer punto en la cita anterior.
El error particular dado en la pregunta,
Illegal mix of collations (latin1_general_cs,IMPLICIT) and (latin1_general_ci,IMPLICIT) for operation '='
nos dice que hubo una comparación de igualdad entre dos cadenas no Unicode de igual coercibilidad. Además, nos dice que las intercalaciones no se dieron explícitamente en la declaración, sino que estaban implícitas en las fuentes de las cadenas (como los metadatos de columna).Eso está muy bien, pero ¿cómo se resuelven esos errores?
Como sugieren los extractos manuales citados anteriormente, este problema se puede resolver de varias maneras, de las cuales dos son razonables y se recomiendan:
Cambie la intercalación de una (o ambas) cadenas para que coincidan y ya no haya ninguna ambigüedad.
La forma en que esto se puede hacer depende de dónde haya venido la cadena: las expresiones literales toman la clasificación especificada en la
collation_connection
variable del sistema; los valores de las tablas toman la clasificación especificada en sus metadatos de columna.Forzar una cadena para que no sea coercible.
Omití la siguiente cita de lo anterior:
Por lo tanto, simplemente agregar una
COLLATE
cláusula a una de las cadenas utilizadas en la comparación forzará el uso de esa intercalación.Mientras que los demás serían terriblemente malas prácticas si se implementaran simplemente para resolver este error:
Obliga a una (o ambas) cadenas a tener algún otro valor de coercibilidad para que tenga prioridad.
El uso de
CONCAT()
oCONCAT_WS()
daría como resultado una cadena con una coercibilidad de 1; y (si está en una rutina almacenada) el uso de parámetros / variables locales daría como resultado cadenas con una coercibilidad de 2.Cambie las codificaciones de una (o ambas) cadenas para que una sea Unicode y la otra no.
Esto podría hacerse mediante la transcodificación con ; o cambiando el conjunto de caracteres subyacente de los datos (por ejemplo, modificando la columna, cambiando valores literales o enviándolos desde el cliente en una codificación diferente y cambiando / agregando un introductor de conjunto de caracteres). Tenga en cuenta que cambiar la codificación provocará otros problemas si algunos caracteres deseados no pueden codificarse en el nuevo conjunto de caracteres.
CONVERT(expr USING transcoding_name)
character_set_connection
character_set_client
Cambie las codificaciones de una (o ambas) cadenas para que sean las mismas y cambie una cadena para usar la
_bin
clasificación relevante .Los métodos para cambiar codificaciones y colaciones se han detallado anteriormente. Este enfoque sería de poca utilidad si uno realmente necesita aplicar reglas de clasificación más avanzadas que las que ofrece la
_bin
clasificación.fuente
Agregar mi 2c a la discusión para futuros googlers.
Estaba investigando un problema similar en el que recibí el siguiente error al usar funciones personalizadas que recibieron un parámetro varchar:
Usando la siguiente consulta:
Pude decir que la base de datos estaba usando utf8_general_ci , mientras que las tablas se definieron usando utf8_unicode_ci :
Tenga en cuenta que las vistas tienen intercalación NULL . Parece que las vistas y funciones tienen definiciones de intercalación, aunque esta consulta muestra nulo para una vista. La clasificación utilizada es la clasificación de base de datos que se definió cuando se creó la vista / función.
La triste solución fue cambiar la colación db y recrear las vistas / funciones para obligarlos a usar la colación actual.
Cambiar la colación de la base de datos:
Cambio de la clasificación de la tabla:
Espero que esto ayude a alguien.
fuente
show full columns from my_table;
alter table <TABLE> modify column <COL> varchar(255) collate utf8_general_ci;
SHOW session variables like '%collation%';
te dice que »collation_connection« es »utf8mb4_general_ci«? Luego corre deSET collation_connection = utf8mb4_unicode_ci
antemano.A veces puede ser peligroso convertir charsets, especialmente en bases de datos con grandes cantidades de datos. Creo que la mejor opción es usar el operador "binario":
fuente
Tuve un problema similar, estaba tratando de usar el procedimiento FIND_IN_SET con una variable de cadena .
y estaba recibiendo el error
Respuesta corta:
No es necesario cambiar ninguna variable colation_YYYY, solo agregue la colación correcta al lado de su declaración de variable , es decir
Respuesta larga:
Primero verifiqué las variables de intercalación:
Luego revisé la clasificación de la tabla:
Esto significa que mi variable se configuró con la clasificación predeterminada de utf8_general_ci mientras que mi tabla se configuró como utf8_unicode_ci .
Al agregar el comando COLLATE junto a la declaración de variables, la clasificación variable coincidió con la clasificación configurada para la tabla.
fuente
Puede probar este script , que convierte todas sus bases de datos y tablas a utf8.
fuente
Solución si hay literales involucrados.
Estoy usando Pentaho Data Integration y no puedo especificar la sintaxis sql. El uso de una búsqueda de base de datos muy simple dio el error "Mezcla ilegal de intercalaciones (cp850_general_ci, COERCIBLE) y (latin1_swedish_ci, COERCIBLE) para la operación '='"
El código generado fue "SELECT DATA_DATE AS latest_DATA_DATE FROM hr_cc_normalised_data_date_v WHERE PSEUDO_KEY =?"
Para abreviar la historia, la búsqueda fue a una vista y cuando emití
que explica de dónde viene el 'cp850_general_ci'.
La vista se creó simplemente con 'SELECCIONAR' X ', ......' De acuerdo con los literales manuales como este, deberían heredar su conjunto de caracteres y su ordenación de la configuración del servidor que se definió correctamente como 'latin1' y 'latin1_general_cs' como este claramente no sucedió lo forcé en la creación de la vista
ahora muestra latin1_general_cs para ambas columnas y el error desapareció. :)
fuente
A MySQL realmente no le gusta mezclar colaciones a menos que pueda forzarlas a la misma (lo que claramente no es factible en su caso). ¿No puede forzar la misma colación para usarla mediante una cláusula COLLATE ? (o el
BINARY
acceso directo más simple si corresponde ...).fuente
Si las columnas con las que tiene problemas son "hashes", considere lo siguiente ...
Si el "hash" es una cadena binaria, realmente debería usar
BINARY(...)
datatype.Si el "hash" es una cadena hexadecimal, no necesita utf8, y debe evitarlo debido a las verificaciones de caracteres, etc. Por ejemplo, MySQL
MD5(...)
produce una cadena hexadecimal de 32 bytes de longitud fija.SHA1(...)
da una cadena hexadecimal de 40 bytes. Esto podría almacenarse enCHAR(32) CHARACTER SET ascii
(o 40 para sha1).O, mejor aún, almacenar
UNHEX(MD5(...))
enBINARY(16)
. Esto reduce a la mitad el tamaño de la columna. (Sin embargo, lo hace bastante no imprimible)SELECT HEX(hash) ...
si lo desea legible.Comparar dos
BINARY
columnas no tiene problemas de intercalación.fuente
Muy interesante ... Ahora, prepárate. Miré todas las soluciones de "agregar intercalación" y para mí, esas son correcciones de curitas. La realidad es que el diseño de la base de datos era "malo". Sí, se agregan cambios estándar y nuevas cosas, bla, bla, pero no cambia el hecho de diseño de la base de datos incorrecta. Me niego a seguir la ruta de agregar "intercalar" en todas las instrucciones SQL solo para que mi consulta funcione. La única solución que funciona para mí y prácticamente eliminará la necesidad de modificar mi código en el futuro es rediseñar la base de datos / tablas para que coincida con el conjunto de caracteres con el que viviré y adoptaré en el futuro a largo plazo. En este caso, elijo ir con el juego de caracteres " utf8mb4 ".
Entonces, la solución aquí cuando encuentre ese mensaje de error "ilegal" es rediseñar su base de datos y tablas. Es mucho más fácil y rápido de lo que parece. Puede que ni siquiera sea necesario exportar sus datos y volver a importarlos desde un CSV. Cambie el conjunto de caracteres de la base de datos y asegúrese de que todo el conjunto de caracteres de sus tablas coincida.
Usa estos comandos para guiarte:
Ahora, si te gusta agregar "intercalar" aquí y allá y reforzar tu código con fuerzas que "anulan" por completo, supongo.
fuente
Una posible solución es convertir toda la base de datos a UTF8 (consulte también esta pregunta ).
fuente
Otra fuente del problema con las colaciones es la
mysql.proc
tabla. Verifique las intercalaciones de sus procedimientos y funciones de almacenamiento:También preste atención a
mysql.proc.collation_connection
ymysql.proc.character_set_client
columnas.fuente
Si tiene instalado phpMyAdmin, puede seguir las instrucciones que figuran en el siguiente enlace: https://mediatemple.net/community/products/dv/204403914/default-mysql-character-set-and-collation Debe coincidir con la clasificación de la base de datos con la de todas las tablas, así como los campos de las tablas y luego volver a compilar todos los procedimientos y funciones almacenados. Con eso todo debería funcionar de nuevo.
fuente
solía
ALTER DATABASE mydb DEFAULT COLLATE utf8_unicode_ci;
, pero no funcionó.En esta consulta:
Este trabajo para mi:
Sí, solo a
concat
.fuente
Este código debe colocarse dentro de Ejecutar consulta / consultas SQL en la base de datos
VENTANA DE CONSULTA SQL
Reemplace table_name y column_name con el nombre apropiado.
fuente