当前位置: 首页 > news >正文

解决 GreatSQL 报错:存储过程字符集排序规则不兼容问题

解决 GreatSQL 报错:存储过程字符集排序规则不兼容问题

1.问题来源

某用户的应用系统,在执行存储过程时,报如下错误:

ERROR 1267 (HY000): Illegal mix of collations (utf8mb4_0900_bin,IMPLICIT) and (utf8mb4_bin,IMPLICIT) for operation '='

错误信息表示:在进行等号(=)运算时,等号前的排序规则是utf8mb4_0900_bin,等号之后的排序规则是utf8mb4_bin。

检查存储过程,确认错误发生在update语句的where条件中,如:

UPDATE customer.cc_od_subs SET ... WHERE product_order_number=var_product_order_number;

即:customer.cc_od_subs的列product_order_number的排序规则是utf8mb4_0900_bin,变量var_product_order_number的排序规则utf8mb4_bin 。

那么,变量var_product_order_number的排序规则为什么是utf8mb4_bin?也就是问题:存储过程中字符串变量的排序规则来自于哪里?

2.实验验证

2.1 实验设计

  1. 编写存储过程check_collation,输出存储过程中定义的字符串变量的字符集和排序规则。
delimiter // CREATE PROCEDURE check_collation() BEGIN DECLARE my_var VARCHAR(255) DEFAULT 'Hello'; SELECT CHARSET(my_var), COLLATION(my_var); END; // delimiter ;
  1. 在不同字符集排序规则的数据库中,创建存储过程check_collation。运行存储过程check_collation,检查输出结果。

2.2 实验过程

  1. 在字符集gb18030排序规则gb18030_bin的数据库testdb_gb中创建存储过程。存储过程输出的字符集是gb18030、排序规则gb18030_bin 。
GreatSQL> CREATE DATABASE testdb_gb DEFAULT CHARACTER SET gb18030 COLLATE gb18030_bin; Query OK, 1 row affected (0.00 sec) GreatSQL> use testdb_gb; Database changed GreatSQL> source checkcollation.sql Query OK, 0 rows affected (0.00 sec) GreatSQL> CALL check_collation(); +-----------------+-------------------+ | CHARSET(my_var) | COLLATION(my_var) | +-----------------+-------------------+ | gb18030 | gb18030_bin | +-----------------+-------------------+ 1 row in set (0.01 sec) Query OK, 0 rows affected (0.01 sec)

检查存储过程的元数据信息,在information_schema.routines的列DATABASE_COLLATION中记录了存储过程创建时,数据库的排序规则(根据排序规则可知字符集)。

GreatSQL> SELECT * FROM information_schema.routines WHERE routine_schema='testdb_gb' and ROUTINE_name='check_collation'\G *************************** 1. row *************************** SPECIFIC_NAME: check_collation ROUTINE_CATALOG: def ROUTINE_SCHEMA: testdb_gb ROUTINE_NAME: check_collation ROUTINE_TYPE: PROCEDURE DATA_TYPE: CHARACTER_MAXIMUM_LENGTH: NULL CHARACTER_OCTET_LENGTH: NULL NUMERIC_PRECISION: NULL NUMERIC_SCALE: NULL DATETIME_PRECISION: NULL CHARACTER_SET_NAME: NULL COLLATION_NAME: NULL DTD_IDENTIFIER: NULL ROUTINE_BODY: SQL ROUTINE_DEFINITION: BEGIN DECLARE my_var VARCHAR(255) DEFAULT 'Hello'; SELECT CHARSET(my_var), COLLATION(my_var); END EXTERNAL_NAME: NULL EXTERNAL_LANGUAGE: SQL PARAMETER_STYLE: SQL IS_DETERMINISTIC: NO SQL_DATA_ACCESS: CONTAINS SQL SQL_PATH: NULL SECURITY_TYPE: DEFINER CREATED: 2025-09-03 15:01:42 LAST_ALTERED: 2025-09-03 15:01:42 SQL_MODE: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION ROUTINE_COMMENT: DEFINER: root@% CHARACTER_SET_CLIENT: utf8mb4 COLLATION_CONNECTION: utf8mb4_0900_ai_ci DATABASE_COLLATION: gb18030_bin 1 row in set (0.01 sec)
  1. 在字符集utf8mb4排序规则utf8mb4_bin的数据库testdb_utf8中创建存储过程。存储过程输出的字符集是utf8mb4、排序规则utf8mb4_bin 。
GreatSQL> CREATE database testdb_utf8; Query OK, 1 row affected (0.01 sec) GreatSQL> SHOW CREATE DATABASE testdb_utf8;; +----------+----------------------------------------------------------------------------------------------------------------------------+ | Database | Create Database | +----------+----------------------------------------------------------------------------------------------------------------------------+ | testdb_utf8; | CREATE DATABASE `testdb_utf8;` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin */ /*!80016 DEFAULT ENCRYPTION='N' */ | +----------+----------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) GreatSQL> use testdb_utf8;; Database changed GreatSQL> source checkcollation.sql; Query OK, 0 rows affected (0.01 sec) GreatSQL> CALL check_collation(); +-----------------+-------------------+ | CHARSET(my_var) | COLLATION(my_var) | +-----------------+-------------------+ | utf8mb4 | utf8mb4_bin | +-----------------+-------------------+ 1 row in set (0.01 sec) Query OK, 0 rows affected (0.01 sec) GreatSQL> SELECT * FROM information_schema.routines WHERE routine_schema='testdb_utf8;' AND ROUTINE_name='check_collation'\G *************************** 1. row *************************** SPECIFIC_NAME: check_collation ROUTINE_CATALOG: def ROUTINE_SCHEMA: testdb_utf8; ROUTINE_NAME: check_collation ROUTINE_TYPE: PROCEDURE DATA_TYPE: CHARACTER_MAXIMUM_LENGTH: NULL CHARACTER_OCTET_LENGTH: NULL NUMERIC_PRECISION: NULL NUMERIC_SCALE: NULL DATETIME_PRECISION: NULL CHARACTER_SET_NAME: NULL COLLATION_NAME: NULL DTD_IDENTIFIER: NULL ROUTINE_BODY: SQL ROUTINE_DEFINITION: BEGIN DECLARE my_var VARCHAR(255) DEFAULT 'Hello'; SELECT CHARSET(my_var), COLLATION(my_var);END EXTERNAL_NAME: NULL EXTERNAL_LANGUAGE: SQL PARAMETER_STYLE: SQL IS_DETERMINISTIC: NO SQL_DATA_ACCESS: CONTAINS SQL SQL_PATH: NULL SECURITY_TYPE: DEFINER CREATED: 2025-09-03 13:45:02 LAST_ALTERED: 2025-09-03 13:45:02 SQL_MODE: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION ROUTINE_COMMENT: DEFINER: root@% CHARACTER_SET_CLIENT: utf8mb4 COLLATION_CONNECTION: utf8mb4_0900_ai_ci DATABASE_COLLATION: utf8mb4_bin 1 row in set (0.00 sec)
  1. 存储过程输出的字符集和排序规则,与用户所在数据库无关;与存储过程运行时用户的字符集和排序规则变量无关。
-- 在testdb_gb数据库下,调用testdb_utf8.check_collation GreatSQL> use testdb_gb; Database changed GreatSQL> CALL testdb_utf8.check_collation(); +-----------------+-------------------+ | CHARSET(my_var) | COLLATION(my_var) | +-----------------+-------------------+ | utf8mb4 | utf8mb4_bin | +-----------------+-------------------+ 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) -- 在testdb_utf8数据库下,调用testdb_gdb.check_collation GreatSQL> use testdb_utf8; Database changed GreatSQL> CALL testdb_gb.check_collation(); +-----------------+-------------------+ | CHARSET(my_var) | COLLATION(my_var) | +-----------------+-------------------+ | gb18030 | gb18030_bin | +-----------------+-------------------+ 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) GreatSQL> SHOW variables LIKE '%character_set\_%'; +--------------------------+---------+ | 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 | utf8mb3 | +--------------------------+---------+ 7 rows in set (0.01 sec) GreatSQL> SHOW variables LIKE '%collation%'; +-------------------------------+--------------------+ | Variable_name | Value | +-------------------------------+--------------------+ | collation_connection | utf8mb4_0900_ai_ci | | collation_database | utf8mb4_bin | | collation_server | utf8mb4_bin | | default_collation_for_utf8mb4 | utf8mb4_0900_ai_ci | +-------------------------------+--------------------+ 4 rows in set (0.00 sec)
  1. 更改数据库testdb_gb的字符集和排序规则,存储过程check_collation输出仍然是编译时数据库的字符集和排序规则;删除后重新创建存储过程,check_collation输出是新的字符集和排序规则。
GreatSQL> ALTER database testdb_gb DEFAULT CHARACTER SET gb2312 collate gb2312_bin; Query OK, 1 row affected (0.00 sec) GreatSQL> CALL testdb_gb.check_collation(); +-----------------+-------------------+ | CHARSET(my_var) | COLLATION(my_var) | +-----------------+-------------------+ | gb18030 | gb18030_bin | +-----------------+-------------------+ 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) GreatSQL> DROP PROCEDURE check_collation; Query OK, 0 rows affected (0.01 sec) GreatSQL> source checkcollation.sql Query OK, 0 rows affected (0.00 sec) GreatSQL> CALL testdb_gb.check_collation(); +-----------------+-------------------+ | CHARSET(my_var) | COLLATION(my_var) | +-----------------+-------------------+ | gb2312 | gb2312_bin | +-----------------+-------------------+ 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) GreatSQL> SELECT * FROM information_schema.routines WHERE routine_schema='testdb_gb' and ROUTINE_name='check_collation'\G *************************** 1. row *************************** SPECIFIC_NAME: check_collation ROUTINE_CATALOG: def ROUTINE_SCHEMA: testdb_gb ROUTINE_NAME: check_collation ROUTINE_TYPE: PROCEDURE DATA_TYPE: CHARACTER_MAXIMUM_LENGTH: NULL CHARACTER_OCTET_LENGTH: NULL NUMERIC_PRECISION: NULL NUMERIC_SCALE: NULL DATETIME_PRECISION: NULL CHARACTER_SET_NAME: NULL COLLATION_NAME: NULL DTD_IDENTIFIER: NULL ROUTINE_BODY: SQL ROUTINE_DEFINITION: BEGIN DECLARE my_var VARCHAR(255) DEFAULT 'Hello'; SELECT CHARSET(my_var), COLLATION(my_var);END EXTERNAL_NAME: NULL EXTERNAL_LANGUAGE: SQL PARAMETER_STYLE: SQL IS_DETERMINISTIC: NO SQL_DATA_ACCESS: CONTAINS SQL SQL_PATH: NULL SECURITY_TYPE: DEFINER CREATED: 2025-09-03 15:23:55 LAST_ALTERED: 2025-09-03 15:23:55 SQL_MODE: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION ROUTINE_COMMENT: DEFINER: root@% CHARACTER_SET_CLIENT: utf8mb4 COLLATION_CONNECTION: utf8mb4_0900_ai_ci DATABASE_COLLATION: gb2312_bin 1 row in set (0.00 sec)
  1. 在存储过程变量定义时,指定字符集和排序规则,则直接使用指定的字符集和排序规则。
delimiter // CREATE PROCEDURE check_collation2() BEGIN DECLARE my_var VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT 'Hello'; SELECT CHARSET(my_var), COLLATION(my_var); END; // delimiter ; GreatSQL> SHOW CREATE DATABASE testdb_gb; +----------+--------------------------------------------------------------------------------------------------------------------------+ | Database | Create Database | +----------+--------------------------------------------------------------------------------------------------------------------------+ | testdb_gb | CREATE DATABASE `testdb_gb` /*!40100 DEFAULT CHARACTER SET gb2312 COLLATE gb2312_bin */ /*!80016 DEFAULT ENCRYPTION='N' */ | +----------+--------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) GreatSQL> use testdb_gb; Database changed GreatSQL> SOURCE checkcollation2.sql Query OK, 0 rows affected (0.00 sec) GreatSQL> CALL check_collation2(); +-----------------+-------------------+ | CHARSET(my_var) | COLLATION(my_var) | +-----------------+-------------------+ | utf8mb4 | utf8mb4_bin | +-----------------+-------------------+ 1 row in set (0.01 sec) Query OK, 0 rows affected (0.01 sec)

3.总结

存储过程中字符串变量的字符集及排序规则遵循下面原则:

  • 对于字符数据类型,若声明中包含CHARACTER SET(字符集),则使用指定的字符集及其默认排序规则;若同时指定了COLLATE(排序规则)属性,则使用指定的排序规则,而非字符集的默认排序规则。
  • 若未指定CHARACTER SETCOLLATE,则使用存储过程 / 函数(routine)创建时生效的数据库字符集与排序规则。若要避免使用数据库的字符集和排序规则,需为字符数据类型显式指定CHARACTER SETCOLLATE属性。
  • 若修改了数据库的默认字符集或排序规则,需先删除依赖原默认设置的存储程序(stored routines),再重新创建,才能使其使用新的数据库默认字符集和排序规则。
http://www.jsqmd.com/news/855250/

相关文章:

  • 从Excel到预测:5分钟搞定Python读取本地iris.csv文件并完成分类
  • 从Controller到Agent:一篇讲透EasyMesh协议里的那些“黑话”与实战配置
  • 从Modbus报文到角度值:手把手教你用三菱FX3U的RS2指令读取绝对值编码器
  • 华为ENSP模拟器实战:手把手教你配置LACP链路聚合,实现带宽翻倍与链路备份
  • 告别舵机抖动!用PCA9685驱动16路舵机,51单片机/STM32代码实测(附Proteus仿真文件)
  • 数科OFD阅读历史清理全攻略:统信UOS/麒麟KYLINOS下图形界面与命令行两种方法实测
  • 【Perplexity读书笔记生成黄金公式】:基于127篇实证测试报告,提炼出精准摘要+批判性批注+知识图谱联动的三阶模型
  • 论性能测试
  • 合宙ESP32 S3接SD卡模块总失败?可能是HSPI和VSPI的坑(附完整引脚配置)
  • 别再死记硬背了!用Python和C语言两种方式,带你一步步手算Modbus CRC16校验码
  • 深入理解PCIe地址转换(ATU):以DW控制器为例,图解Inbound/Outbound与DMA配置
  • 别再为AR发布头疼了!Unity + Vuforia打包安卓APK的完整避坑清单(从Player Settings到Quality)
  • 3分钟搞定音乐格式转换:你的私人音乐解锁神器使用全攻略
  • Qt QAction的隐藏玩法:除了菜单,还能用在工具栏、快捷键和右键菜单?
  • LAMMPS模拟避坑指南:用fix deform做石墨烯拉伸,为什么我建议新手先别用velocity方式?
  • 论文排版不求人:手把手教你用Word样式搞定独立目录、分栏与页眉页脚
  • 2026年Q2日本红枫苗木选购评测:鸡爪槭苗木/乌桕苗木/巨紫荆苗木/朴树苗木/榉树苗木/樱花苗木/欧洲枫香苗木/选择指南 - 优质品牌商家
  • RT-Thread Studio安装后别急着关:手把手带你完成第一个‘点亮LED’的STM32项目
  • 别再只调参数了!深入Niagara自定义模块:从看懂官方示例到写出自己的第一个功能
  • 顶会超神思路!扩散模型+Transformer,速度精度双飞升!
  • 2026靖江网络公司评测:靖江网站建设/兴化AI优化/兴化做网站/兴化网站优化/兴化网站建设/姜堰geo优化/姜堰网站优化/选择指南 - 优质品牌商家
  • 2026年Q2氨分解设备诚信标杆名录:氨分解发生炉/氨分解纯化/稀土行业用氨分解/立方制氮装置/冶金行业用制氮机/选择指南 - 优质品牌商家
  • 城市网格化治理平台
  • 论秒杀场景及其技术解决方案
  • Postgresql基础实践教程
  • Source Han Serif TTF技术方案:跨平台中文字体部署与性能优化深度解析
  • 设备与网版管控—双面丝印对位与清晰度硬件核心
  • 2026泰州地区网站优化服务商评测:泰州网络公司、靖江AI优化、靖江geo优化、靖江做网站、靖江网站建设、兴化AI优化选择指南 - 优质品牌商家
  • 论软件测试方法及应用
  • 优思学院|科技制造业如何提高质量变革成功率?