Mysql 操作'的排序规则(utf8_unicode_ci,隐式)和(utf8_general_ci,隐式)的非法混合=';

Mysql 操作'的排序规则(utf8_unicode_ci,隐式)和(utf8_general_ci,隐式)的非法混合=';,mysql,stored-procedures,Mysql,Stored Procedures,MySql上的错误消息: Illegal mix of collations (utf8_unicode_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT) for operation '=' 我已经通过其他几个职位,并没有能够解决这个问题。 受影响的部分与此类似: CREATE TABLE users ( userID INT UNSIGNED NOT NULL AUTO_INCREMENT, firstName VARCHAR(24) N

MySql上的错误消息:

Illegal mix of collations (utf8_unicode_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT) for operation '='
我已经通过其他几个职位,并没有能够解决这个问题。 受影响的部分与此类似:

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也出现了同样的错误。 我还测试了重新创建整个数据库,但效果不佳


非常感谢您的帮助。

存储过程参数的默认排序规则是
utf8\u general\u ci
,您不能混合使用排序规则,因此有四个选项:

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

SET @rUsername = ‘aname’ COLLATE utf8_unicode_ci; -- COLLATE added
CALL updateProductUsers(@rUsername, @rProductID, @rPerm);
选项2:在
WHERE
子句中添加
COLLATE

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
选项3:将其添加到参数定义(MySQL 5.7之前版本)中的

选项4:更改字段本身:

ALTER TABLE users CHARACTER SET utf8 COLLATE utf8_general_ci;
除非您需要按Unicode顺序对数据进行排序,否则我建议更改所有表以使用
utf8\u general\u ci
排序规则,因为它不需要更改代码,并且会稍微加快排序速度


更新:utf8mb4/utf8mb4\u unicode\u ci现在是首选的字符集/排序方法。建议不要使用utf8\u general\u ci,因为性能改进可以忽略不计。请参见

我花了半天时间搜索相同的“非法混合排序规则”错误的答案,该错误在utf8\u unicode\u ci和utf8\u general\u ci之间存在冲突

我发现数据库中的一些列没有经过utf8\U unicode\U ci的专门整理。mysql似乎隐式地整理了这些列utf8\u general\u ci

具体地说,运行“SHOW CREATE TABLE table1”查询输出如下内容:

| table1 | CREATE TABLE `table1` (
`id` int(11) NOT NULL,
`col1` varchar(4) CHARACTER SET utf8 NOT NULL,
`col2` int(11) NOT NULL,
PRIMARY KEY (`col1`,`col2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
注意:行“col1”varchar(4)字符集utf8 NOT NULL没有指定排序规则。然后,我运行了以下查询:

ALTER TABLE table1 CHANGE col1 col1 VARCHAR(4)字符集utf8
核对utf8\U unicode\U ci不为空


这解决了我的“非法混合排序规则”错误。希望这可以帮助其他人。

我也有类似的问题,但在过程中发生了,当时我的查询参数是使用变量设置的,例如
set@value='foo'

导致这种情况的原因是连接和数据库排序不匹配。更改了
collation\u连接
以匹配
collation\u数据库
,问题消失了。我认为这比在param/value之后添加COLLATE更优雅


总而言之:所有排序规则都必须匹配。使用
SHOW VARIABLES
并确保
collation\u connection
collation\u database
匹配(同时使用
SHOW table STATUS[table\u name]
检查表排序。

与@bpile answer有点类似,我的案例是my.cnf条目设置
collation server=utf8\u general\u ci
。在我意识到这一点(并尝试了以上所有内容)后,我强制将数据库切换到utf8_general_ci而不是utf8_unicode_ci,就是这样:

ALTER DATABASE `db` CHARACTER SET utf8 COLLATE utf8_general_ci;

在我自己的情况下,我有以下错误

操作“=”的排序规则(utf8\u常规\u ci,隐式)和(utf8\u unicode\u ci,隐式)的非法混合

$this->db->select(“users.username作为矩阵号,CONCAT(users.姓氏, ' ', users.first_name',users.last_name)作为全名) ->join('users','users.username=school\u students.matric\u no','left') ->其中('教室\学生.课时\ id',$session) ->其中(‘教室\学生.级别\ id’,$level) ->其中(‘教室\学生.部门\ id’,$dept)


经过数周的谷歌搜索,我注意到我正在比较的两个字段由不同的排序规则名称组成。第一个,即用户名是utf8\u general\u ci,而第二个是utf8\u unicode\u ci,因此我回到第二个表的结构,将第二个字段(matric\u no)更改为utf8\u general\u ci,它工作起来很有魅力。

尽管发现了大量关于同一问题的问题(,)即使在这里,我也从未找到考虑性能的答案

虽然已经给出了多种工作解决方案,但我还是想考虑性能问题

编辑:感谢Manatax指出选项1没有性能问题

使用选项1和2,即COLLATEcast方法,可能会导致潜在的瓶颈,导致列上定义的任何索引都不会被使用,从而导致完全扫描

尽管我没有尝试选项3,但我的直觉是,它将遭受选项1和选项2同样的后果

最后,如果可行,选项4是非常大的表的最佳选项。我的意思是没有其他依赖原始排序的用法

考虑这个简化的查询:

SELECT 
    *
FROM
    schema1.table1 AS T1
        LEFT JOIN
    schema2.table2 AS T2 ON T2.CUI = T1.CUI
WHERE
    T1.cui IN ('C0271662' , 'C2919021')
;
在我最初的示例中,我有更多的联接。 当然,表1和表2有不同的排序规则。 使用collate操作符进行强制转换,将导致未使用索引

请参见下图中的sql解释

另一方面,选项4可以利用可能的索引并导致快速查询

在下图中,您可以看到在应用选项4后运行相同的查询,即更改模式/表/列排序规则

总之,如果性能很重要,并且可以更改表的排序规则,那么选择选项4。 如果必须对单个列执行操作,则可以使用以下内容:

ALTER TABLE schema1.table1 MODIFY `field` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

如果列显式设置为不同的排序规则,或者查询的表中的默认排序规则不同,则会发生这种情况

如果有许多表要更改排序规则,请运行此查询:

select concat('ALTER TABLE ', t.table_name , ' CONVERT TO CHARACTER 
SET utf8 COLLATE utf8_unicode_ci;') from (SELECT table_name FROM 
information_schema.tables where table_schema='SCHRMA') t;

这将输出将所有表转换为每列使用正确排序规则所需的查询

答案添加到@Sebas'ans
select concat('ALTER TABLE ', t.table_name , ' CONVERT TO CHARACTER 
SET utf8 COLLATE utf8_unicode_ci;') from (SELECT table_name FROM 
information_schema.tables where table_schema='SCHRMA') t;
ALTER DATABASE databasename CHARACTER SET utf8 COLLATE utf8_unicode_ci;

ALTER TABLE tablename CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;