2012-08-02 77 views
96

错误味精的非法组合:归类(utf8_unicode_ci,隐含的)的操作 '='归类(utf8_unicode_ci,IMPLICIT)和(utf8_general_ci,隐含的)上进行操作的MySQL '='

非法混合物和(utf8_general_ci,隐含的)

我已经经历了其他几个职位,无法解决这个问题。 受影响的部分是与此类似:

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; 

我使用的存储过程是这样的:

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 

我是用PHP进行测试,但与SQLyog的给出了同样的错误。 我也测试过重新创建整个数据库,但没有成功。

任何帮助将不胜感激。

回答

136

有四个选项:

选项1:添加COLLATE您输入变量:

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

选项2:添加COLLATEWHERE条款:

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:它添加到IN参数定义:

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 

选项4:改变字段本身:

ALTER TABLE users CHARACTER SET utf8 COLLATE utf8_general_ci; 

作为用于存储过程参数的默认排序是utf8_general_ci和你不能混合排序。

除非您需要按Unicode顺序对数据进行排序,否则我会建议更改您的所有表以使用utf8_general_ci排序规则,因为它不需要更改代码,并且速度会略微提高。

+0

你的第一选择是我一直在寻找=答案)。谢谢。 – Manatax 2012-08-02 02:49:00

+1

另外,也可以添加'COLLATE utf8_unicode_ci'到字符串常量: 'SET @EMAIL = '[email protected]' COLLATE utf8_unicode_ci;'。如果您正在从控制台运行脚本,其中控制台默认编码适用于您的字符串常量的归类,这一点尤其有用。 – gaborsch 2016-05-05 10:35:22

+0

或者放下数据库并用utf8_general_ci创建新的;排序规则。 – Oleksii 2017-04-01 22:05:17

16

我花了半天的时间寻找与UTF8_unicode_ci和utf8_general_ci之间的冲突相同的“非法混合混合”错误的答案。

我发现我的数据库中的某些列没有特别整理utf8_unicode_ci。看起来mysql隐含地整理了这些列utf8_general_ci

具体而言,运行 'SHOW CREATE TABLE表1' 查询输出类似如下:

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

注线'COL1' VARCHAR(4)字符集UTF8 NOT NULL不具有核对指定。然后,我跑到下面的查询:

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

这解决了我的错误“的归类非法组合”。希望这可能会帮助其他人。

+4

谢谢。 'SHOW CREATE TABLE'是理解和解决问题根源的最简单方法。 – joro 2016-01-25 11:44:04

4

我也有类似的问题,但它使用可变例如发生在我里面的程序,当我的查询参数设置SET @value='foo'

是什么造成了这种不匹配的是和collation_connection数据库归类。更改collation_connection以匹配collation_database并且问题消失。我认为这比在param/value之后添加COLLATE更加优雅。

总结:所有排序规则必须匹配。使用SHOW VARIABLES并确保collation_connectioncollation_database比赛(也检查使用SHOW TABLE STATUS [table_name]表排序)。

+0

同样的问题发生在我身上,我通过直接在变量声明中设置排序规则来避免更改collat​​ion_YYY变量。 'SET @my_var =“字符串1,字符串” COLLATE utf8_unicode_ci;' – nkatsar 2017-10-10 16:44:05

1

有点类似于@bpile答案,我的情况是my.cnf中的条目设置collation-server = utf8_general_ci。之后我意识到(及以上乱投医后),我强行打开我的数据库utf8_general_ci,而不是utf8_unicode_ci,就是这样:

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

很奇怪的是,配置传遍了这么多。所有排序规则默认值应设置在相同的位置。 – Manatax 2016-12-07 19:35:54

相关问题