MySQL表排序规则不同错误问题分析
MySQL多表join时报错如下:[Err]1267–Illegalmixofcollations(utf8_general_ci,IMPLICIT)and(utf8_unicode_ci,IMPLICIT)foroperation‘=
就是说两个表的排序规则(COLLATION)不同,无法完成比较。COLLATION是用在排序,大小比较上,一个字符集有一个或多种COLLATION,并且以_ci(大小写不敏感)、_cs(大小写敏感)或_bin(二进制)结束。在做比较时,应该确保两个表的字符排序相同。一般建表的时候不指定,可以走默认的,全是默认的就没什么问题了。
下面来模拟一下各种场景,表结构如下(utf8默认排序规则为utf8_general_ci):
mysql>showcreatetabletest.cs\G ***************************1.row*************************** Table:cs CreateTable:CREATETABLE`cs`( `id`int(11)DEFAULTNULL, `name`varchar(10)DEFAULTNULL )ENGINE=InnoDBDEFAULTCHARSET=utf8 1rowinset(0.01sec)
查看表默认排序规则集
mysql>selectTABLE_SCHEMA,TABLE_NAME,TABLE_COLLATIONfrominformation_schema.tableswheretable_name='cs'; +--------------+------------+-----------------+ |TABLE_SCHEMA|TABLE_NAME|TABLE_COLLATION| +--------------+------------+-----------------+ |test|cs|utf8_general_ci| +--------------+------------+-----------------+ 1rowinset(0.00sec)
查看列排序规则集
mysql>selectTABLE_SCHEMA,TABLE_NAME,COLUMN_NAME,COLLATION_NAMEfrominformation_schema.COLUMNSwhereTABLE_NAME='cs'; +--------------+------------+-------------+-----------------+ |TABLE_SCHEMA|TABLE_NAME|COLUMN_NAME|COLLATION_NAME| +--------------+------------+-------------+-----------------+ |test|cs|id|NULL| |test|cs|name|utf8_general_ci| +--------------+------------+-------------+-----------------+ 2rowsinset(0.00sec)
从utf8升级为utf8mb4是不支持onlineddl的,如下:
mysql>ALTERTABLEcsCONVERTTOCHARACTERSETutf8mb4,ALGORITHM=INPLACE,LOCK=NONE; ERROR1846(0A000):ALGORITHM=INPLACEisnotsupported.Reason:CannotchangecolumntypeINPLACE.TryALGORITHM=COPY.
从utf8.utf8_general_ci变更为utf8.utf8_unicode_ci是不支持onlineddl的,如下:
mysql>ALTERTABLEcsCONVERTTOCHARACTERSETutf8collateutf8_unicode_ci,ALGORITHM=INPLACE,LOCK=NONE; ERROR1846(0A000):ALGORITHM=INPLACEisnotsupported.Reason:CannotchangecolumntypeINPLACE.TryALGORITHM=COPY.
如果使用下面这种方式修改字符集,你会发现,只更改了表级的,没有更改列级的。
mysql>ALTERTABLEcsCHARACTERSETutf8collateutf8_unicode_ci; QueryOK,0rowsaffected(0.01sec) Records:0Duplicates:0Warnings:0 mysql>selectTABLE_SCHEMA,TABLE_NAME,TABLE_COLLATIONfrominformation_schema.tableswheretable_name='cs'; +--------------+------------+-----------------+ |TABLE_SCHEMA|TABLE_NAME|TABLE_COLLATION| +--------------+------------+-----------------+ |test|cs|utf8_unicode_ci| +--------------+------------+-----------------+ 1rowinset(0.00sec) mysql>selectTABLE_SCHEMA,TABLE_NAME,COLUMN_NAME,COLLATION_NAMEfrominformation_schema.COLUMNSwhereTABLE_NAME='cs'; +--------------+------------+-------------+-----------------+ |TABLE_SCHEMA|TABLE_NAME|COLUMN_NAME|COLLATION_NAME| +--------------+------------+-------------+-----------------+ |test|cs|id|NULL| |test|cs|name|utf8_general_ci| +--------------+------------+-------------+-----------------+ 2rowsinset(0.00sec)
所以真正改字符集的时候别忘了加上CONVERTTO,如下:
mysql>ALTERTABLEcsCONVERTTOCHARACTERSETutf8collateutf8_unicode_ci; QueryOK,5rowsaffected(0.06sec) Records:5Duplicates:0Warnings:0 mysql>selectTABLE_SCHEMA,TABLE_NAME,COLUMN_NAME,COLLATION_NAMEfrominformation_schema.COLUMNSwhereTABLE_NAME='cs'; +--------------+------------+-------------+-----------------+ |TABLE_SCHEMA|TABLE_NAME|COLUMN_NAME|COLLATION_NAME| +--------------+------------+-------------+-----------------+ |test|cs|id|NULL| |test|cs|name|utf8_unicode_ci| +--------------+------------+-------------+-----------------+ 2rowsinset(0.00sec)
要仅仅改变一个表的默认字符集,应使用此语句:
mysql>ALTERTABLEcsdefaultCHARACTERSETutf8collateutf8_general_ci,ALGORITHM=INPLACE,LOCK=NONE; QueryOK,0rowsaffected(0.00sec) Records:0Duplicates:0Warnings:0 mysql>selectTABLE_SCHEMA,TABLE_NAME,TABLE_COLLATIONfrominformation_schema.tableswheretable_name='cs'; +--------------+------------+-----------------+ |TABLE_SCHEMA|TABLE_NAME|TABLE_COLLATION| +--------------+------------+-----------------+ |test|cs|utf8_general_ci| +--------------+------------+-----------------+ 1rowinset(0.00sec) mysql>selectTABLE_SCHEMA,TABLE_NAME,COLUMN_NAME,COLLATION_NAMEfrominformation_schema.COLUMNSwhereTABLE_NAME='cs'; +--------------+------------+-------------+-----------------+ |TABLE_SCHEMA|TABLE_NAME|COLUMN_NAME|COLLATION_NAME| +--------------+------------+-------------+-----------------+ |test|cs|id|NULL| |test|cs|name|utf8_unicode_ci| +--------------+------------+-------------+-----------------+ 2rowsinset(0.00sec)
可以发现列字符集没有改变,并且只有新的列才会默认继承表的字符集(utf8.utf8_general_ci)。
总结
以上就是本文关于MySQL表排序规则不同错误问题分析的全部内容,希望对大家有所帮助。感兴趣的朋友可以参阅:几个比较重要的MySQL变量、MySQL声明变量及存储过程分析、MySQL主库binlog(master-log)与从库relay-log关系代码详解、MySQLprepare原理详解等,有什么问题可以随时留言,互相交流,共同进步。