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,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,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_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,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,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,LOCK=NONE; Query OK,0 rows affected (0.00 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> select TABLE_SCHEMA,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,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原理詳解等,有什麼問題可以隨時留言,互相交流,共同進步。