MySQL表排序规则不同错误问题分析
mysql多表join时报错如下:[err]1267 – illegal mix of collations(utf8_general_ci,implicit) and (utf8_unicode_ci,implicit) for operation ‘=
就是说两个表的排序规则(collation)不同,无法完成比较。collation是用在排序,大小比较上,一个字符集有一个或多种collation,并且以_ci(大小写不敏感)、_cs(大小写敏感)或_bin(二进制)结束。在做比较时,应该确保两个表的字符排序相同。一般建表的时候不指定,可以走默认的,全是默认的就没什么问题了。
下面来模拟一下各种场景,表结构如下(utf8默认排序规则为utf8_general_ci):
mysql> show create table test.cs\g *************************** 1. row *************************** table: cs create table: create table `cs` ( `id` int(11) default null, `name` varchar(10) default null ) engine=innodb default charset=utf8 1 row in set (0.01 sec)
查看表默认排序规则集
mysql> select table_schema,table_name,table_collation from information_schema.tables where table_name='cs'; +--------------+------------+-----------------+ | table_schema | table_name | table_collation | +--------------+------------+-----------------+ | test | cs | utf8_general_ci | +--------------+------------+-----------------+ 1 row in set (0.00 sec)
查看列排序规则集
mysql> select table_schema,table_name,column_name,collation_name from information_schema.columns where table_name='cs'; +--------------+------------+-------------+-----------------+ | table_schema | table_name | column_name | collation_name | +--------------+------------+-------------+-----------------+ | test | cs | id | null | | test | cs | name | utf8_general_ci | +--------------+------------+-------------+-----------------+ 2 rows in set (0.00 sec)
从utf8升级为utf8mb4是不支持online ddl的,如下:
mysql> alter table cs convert to character set utf8mb4,algorithm=inplace,lock=none; error 1846 (0a000): algorithm=inplace is not supported. reason: cannot change column type inplace. try algorithm=copy.
从utf8.utf8_general_ci变更为utf8.utf8_unicode_ci是不支持online ddl的,如下:
mysql> alter table cs convert to character set utf8 collate utf8_unicode_ci,algorithm=inplace,lock=none; error 1846 (0a000): algorithm=inplace is not supported. reason: cannot change column type inplace. try algorithm=copy.
如果使用下面这种方式修改字符集,你会发现,只更改了表级的,没有更改列级的。
mysql> alter table cs character set utf8 collate utf8_unicode_ci; query ok, 0 rows affected (0.01 sec) records: 0 duplicates: 0 warnings: 0 mysql> select table_schema,table_name,table_collation from information_schema.tables where table_name='cs'; +--------------+------------+-----------------+ | table_schema | table_name | table_collation | +--------------+------------+-----------------+ | test | cs | utf8_unicode_ci | +--------------+------------+-----------------+ 1 row in set (0.00 sec) mysql> select table_schema,table_name,column_name,collation_name from information_schema.columns where table_name='cs'; +--------------+------------+-------------+-----------------+ | table_schema | table_name | column_name | collation_name | +--------------+------------+-------------+-----------------+ | test | cs | id | null | | test | cs | name | utf8_general_ci | +--------------+------------+-------------+-----------------+ 2 rows in set (0.00 sec)
所以真正改字符集的时候别忘了加上convert to,如下:
mysql> alter table cs convert to character set utf8 collate utf8_unicode_ci; query ok, 5 rows affected (0.06 sec) records: 5 duplicates: 0 warnings: 0 mysql> select table_schema,table_name,column_name,collation_name from information_schema.columns where table_name='cs'; +--------------+------------+-------------+-----------------+ | table_schema | table_name | column_name | collation_name | +--------------+------------+-------------+-----------------+ | test | cs | id | null | | test | cs | name | utf8_unicode_ci | +--------------+------------+-------------+-----------------+ 2 rows in set (0.00 sec)
要仅仅改变一个表的默认字符集,应使用此语句:
mysql> alter table cs default character set utf8 collate utf8_general_ci,algorithm=inplace,lock=none; query ok, 0 rows affected (0.00 sec) records: 0 duplicates: 0 warnings: 0 mysql> select table_schema,table_name,table_collation from information_schema.tables where table_name='cs'; +--------------+------------+-----------------+ | table_schema | table_name | table_collation | +--------------+------------+-----------------+ | test | cs | utf8_general_ci | +--------------+------------+-----------------+ 1 row in set (0.00 sec) mysql> select table_schema,table_name,column_name,collation_name from information_schema.columns where table_name='cs'; +--------------+------------+-------------+-----------------+ | table_schema | table_name | column_name | collation_name | +--------------+------------+-------------+-----------------+ | test | cs | id | null | | test | cs | name | utf8_unicode_ci | +--------------+------------+-------------+-----------------+ 2 rows in set (0.00 sec)
可以发现列字符集没有改变,并且只有新的列才会默认继承表的字符集(utf8.utf8_general_ci)。
总结
以上就是本文关于mysql表排序规则不同错误问题分析的全部内容,希望对大家有所帮助。感兴趣的朋友可以参阅:几个比较重要的mysql变量、mysql 声明变量及存储过程分析、mysql主库binlog(master-log)与从库relay-log关系代码详解、mysql prepare原理详解等,有什么问题可以随时留言,互相交流,共同进步。