2012-08-02 6 views
96
msg

Error en MySql: mezcla ilegal de intercalaciones (utf8_unicode_ci, implícita) y (utf8_general_ci, implícita) para la operación '='mezcla ilegal de intercalaciones (utf8_unicode_ci, implícita) y (utf8_general_ci, implícita) para el funcionamiento '='

He pasado por varias otras publicaciones y no he podido resolver este problema. La parte afectada es algo similar a esto:

CREATE TABLE users (
    userID INT UNSIGNED NOT NULL AUTO_INCREMENT, 
    firstName VARCHAR(24) NOT NULL, 
    lastName VARCHAR(24) NOT NULL, 
    username VARCHAR(24) NOT NULL, 
    password VARCHAR(40) NOT NULL, 
    PRIMARY KEY (userid) 
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci; 

CREATE TABLE products (
    productID INT UNSIGNED NOT NULL AUTO_INCREMENT, 
    title VARCHAR(104) NOT NULL, 
    picturePath VARCHAR(104) NULL, 
    pictureThumb VARCHAR(104) NULL, 
    creationDate DATE NOT NULL, 
    closeDate DATE NULL, 
    deleteDate DATE NULL, 
    varPath VARCHAR(104) NULL, 
    isPublic TINYINT(1) UNSIGNED NOT NULL DEFAULT '1', 
    PRIMARY KEY (productID) 
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci; 

CREATE TABLE productUsers (
    productID INT UNSIGNED NOT NULL, 
    userID INT UNSIGNED NOT NULL, 
    permission VARCHAR(16) NOT NULL, 
    PRIMARY KEY (productID,userID), 
    FOREIGN KEY (productID) REFERENCES products (productID) ON DELETE RESTRICT ON UPDATE NO ACTION, 
    FOREIGN KEY (userID) REFERENCES users (userID) ON DELETE RESTRICT ON UPDATE NO ACTION 
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci; 

El procedimiento almacenado que estoy usando es la siguiente:

CREATE PROCEDURE updateProductUsers (IN rUsername VARCHAR(24),IN rProductID INT UNSIGNED,IN rPerm VARCHAR(16)) 
BEGIN 
    UPDATE productUsers 
     INNER JOIN users 
     ON productUsers.userID = users.userID 
     SET productUsers.permission = rPerm 
     WHERE users.username = rUsername 
     AND productUsers.productID = rProductID; 
END 

estaba probando con php, pero el mismo error se da con SQLyog. También probé recreando toda la base de datos, pero para nada.

Cualquier ayuda será muy apreciada.

Respuesta

136

hay cuatro opciones:

Opción 1: añadir COLLATE a la variable de entrada:

SET @rUsername = ‘aname’ COLLATE utf8_unicode_ci; -- COLLATE added 
CALL updateProductUsers(@rUsername, @rProductID, @rPerm); 

Opción 2: añadir COLLATE a la WHERE cláusula:

CREATE PROCEDURE updateProductUsers(
    IN rUsername VARCHAR(24), 
    IN rProductID INT UNSIGNED, 
    IN rPerm VARCHAR(16)) 
BEGIN 
    UPDATE productUsers 
     INNER JOIN users 
     ON productUsers.userID = users.userID 
     SET productUsers.permission = rPerm 
     WHERE users.username = rUsername COLLATE utf8_unicode_ci -- COLLATE added 
     AND productUsers.productID = rProductID; 
END 

Optio n 3: añadirlo a la definición IN parámetro:

CREATE PROCEDURE updateProductUsers(
    IN rUsername VARCHAR(24) COLLATE utf8_unicode_ci, -- COLLATE added 
    IN rProductID INT UNSIGNED, 
    IN rPerm VARCHAR(16)) 
BEGIN 
    UPDATE productUsers 
     INNER JOIN users 
     ON productUsers.userID = users.userID 
     SET productUsers.permission = rPerm 
     WHERE users.username = rUsername 
     AND productUsers.productID = rProductID; 
END 

Opción 4: alterar el propio campo:

ALTER TABLE users CHARACTER SET utf8 COLLATE utf8_general_ci; 

como la colación por defecto para los parámetros de procedimiento almacenado es utf8_general_ci y se puede' t mezclar colaciones

A menos que necesite ordenar los datos en orden Unicode, le sugiero que modifique todas las tablas para usar la intercalación utf8_general_ci, ya que no requiere cambios de código, y la velocidad se ordena ligeramente.

+0

Su primera opción era la respuesta que estaba buscando =). Gracias. – Manatax

+1

También es posible agregar 'COLLATE utf8_unicode_ci' a las constantes de cadena: ' SET @EMAIL = '[email protected]' COLLATE utf8_unicode_ci; '. Es especialmente útil si ejecuta un script desde una consola, donde la codificación predeterminada de la consola se aplica a la intercalación de las constantes de cadena. – gaborsch

+0

O suelte la base de datos y cree una nueva con utf8_general_ci; colación. – Oleksii

16

Pasé medio día buscando respuestas a un error idéntico de "combinación ilegal de intercalaciones" con conflictos entre utf8_unicode_ci y utf8_general_ci.

Encontré que algunas columnas en mi base de datos no se recopilaron específicamente utf8_unicode_ci. Parece que mysql cotejó implícitamente estas columnas utf8_general_ci.

Específicamente, ejecutar una consulta 'SHOW CREATE TABLE tabla1' emitida algo como lo siguiente:

| table1 | CREATE TABLE `table1` (
`id` int(11) NOT NULL, 
`col1` varchar(4) CHARACTER SET utf8 NOT NULL, 
`col2` int(11) NOT NULL, 
PRIMARY KEY (`photo_id`,`tag`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci | 

Nota varchar la línea 'col1' (4) CARACTERES UTF8 NO NULO no tiene una colación especificado.entonces me encontré con la siguiente consulta:

ALTER TABLE table1 CHANGE col1 col1 VARCHAR(4) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL;

Esto resolvió mi "mezcla ilegal de colaciones" error. Espero que esto pueda ayudar a alguien más allá.

+4

gracias. 'SHOW CREATE TABLE' es la forma más fácil de comprender y corregir la causa raíz del problema. – joro

4

Tuve un problema similar, pero se me ocurrió hacerlo dentro del procedimiento, cuando mi parámetro de consulta se configuró utilizando una variable, p. SET @value='foo'.

Lo que está causando el error collation_connection y la intercalación de la base de datos. Cambió collation_connection para que coincida con collation_database y el problema desapareció. Creo que este es un enfoque más elegante que agregar COLLATE después de param/value.

En resumen: todas las intercalaciones deben coincidir. Use SHOW VARIABLES y asegúrese de que collation_connection y collation_database coincidan (también consulte la clasificación de la tabla usando SHOW TABLE STATUS [table_name]).

+0

Se me ocurrió el mismo problema, evité cambiar las variables de colación_YYY estableciendo la intercalación directamente en la declaración de variable. 'SET @my_var = 'cadena1, cadena2' COLLATE utf8_unicode_ci;' – nkatsar

1

Un poco similar a @bpile answer, mi caso fue una configuración de entrada my.cnf collation-server = utf8_general_ci. Después me di cuenta de que (y después de probar todo lo anterior), que fuerza cambié mi base de datos a utf8_general_ci en lugar de utf8_unicode_ci y eso fue todo:

ALTER DATABASE `db` CHARACTER SET utf8 COLLATE utf8_general_ci; 
+1

Es extraño que las configuraciones se distribuyan tanto. Todos los valores predeterminados de intercalación deben establecerse en el mismo lugar. – Manatax

Cuestiones relacionadas