2020年5月15日 星期五

mysql: Illegal mix of collations (utf8_unicode_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT) for operation '=

以下整理一下結論:

1. 所有的都改成 utf8mb4/utf8_unicode_ci

產生不一致的情形時,就是 Store Procedure/Trigger 裡面的變數、參數

使用時,都再指定為 utf8mb4_unicode_ci

資料寫說,不要用 general_ci了


以下是網友的網頁,留下來參考

mysql: Illegal mix of collations (utf8_unicode_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT) for operation '= 的解决

昨天把mysql里所有table的varchar字段的字符集,批量换成了utf8mb4/utf8mb4_unicode_ci ,以便能保存一些emoji火星文 , 结果有一个sql语句执行时,报错如下:
Illegalmixofcollations (utf8_unicode_ci,IMPLICITand (utf8_general_ci,IMPLICIT)foroperation '=
观察了一下,这个sql使用了一个自定义的function,这个函数的入口参数为varchar,类似如下:
CREATE FUNCTION `f_xxx`(
  p_ref_type     VARCHAR(50) ,
  ...
)
问题就在这里,把p_ref_type的参数类型改成:
CREATE FUNCTION `f_xxx`(
  p_ref_type     VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
  ...
)
就ok了。

当然,如果不想改function,还有一种一劳永逸的解决办法:(需要停机)
出错信息的意思是 utf8-unicode-cli与utf-general-cli 不能混用,可以用
show create function f_xxx\G 查看下结构,重点观察下最后几行:
复制代码
...

  END
character_set_client: utf8mb4
collation_connection: utf8mb4_unicode_ci
  Database Collation: utf8_general_ci
1 row in set (0.00 sec)
复制代码
这里可以看出,collation_connnection 与 Database Collation所用的字符集不一致,要想办法弄成一致,可以再用:
SHOW VARIABLES WHERE Variable_name LIKE 'character_set_%' OR Variable_name LIKE 'collation%';
查看mysql的相关系统变量:
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
| collation_connection | utf8mb4_general_ci |
| collation_database | utf8mb4_general_ci |
| collation_server | utf8mb4_general_ci |
大概输出是这样的,注意最后3行,确认mysql实例的编码后,可以调整database的编码:
ALTER DATABASE `数据库名` character set utf8mb4 COLLATE utf8mb4_general_ci ;
考虑到,有些表或字段在创建时,可能也指定了其它编码,可以用:
./mysqldump -u用户名 -p -d --add-drop-table 数据库名 > 导出的文件名
注:为防止操作期间有人操作数据库,最好将所有应用暂时停机,保证操作期间db没人向其写入数据 。
导出表结构的sql,然后用文本编码工具,批量把指定字符集的字符串给批量清空,即:清除所有指定字符集的DDL语句,全部默认用database本身的字符集
接下来用
./mysqldump -u用户名 -p -t 数据库名 > 导出的文件名 
导出所有数据
最后,干掉所有table,然后mysql命令行下
source 修改好以后的数据库表结构.sql
source 数据.sql
将所有表重建,然后导入数据,进行恢复,最终目标是将整个db,包括所有表及字段的字符集大换血了

沒有留言:

張貼留言

如何判斷現在FORM是在 insert mode? 還是 update mode?

只要用  if (empty({primary_key})) 就可以知道是否為新增模式了。 如果 {promary_key} 是空白的,那麼就是在新增模式;反之,就是更新模式。 以上。