存储过程字符集问题必须四层同步校准:客户端连接、数据库定义、过程创建、动态拼接;最常见源头是CREATE PROCEDURE前未SET NAMES utf8mb4,导致中文注释及字面量入库即损坏。

存储过程报错直接源于字符集链路断裂,不是改个表就能好——必须从客户端连接、数据库定义、过程创建、动态拼接四层同步校准。
执行 CREATE PROCEDURE 前没 SET NAMES utf8mb4
这是最隐蔽也最高发的源头:过程体内的中文(包括注释、字符串字面量、DECLARE 默认值)在客户端发送 SQL 时就被按错误字符集解析了,入库即损坏,后续无法修复。
- 现象:SHOW CREATE PROCEDURE 显示中文注释变成 ??? 或乱码,哪怕库和表都是 utf8mb4
- 原因:mysql 命令行默认用 latin1 连接,
CREATE PROCEDURE语句里的中文被截断或转义成无效字节 - 解决:在
DELIMITER之前、CREATE PROCEDURE之后第一行加SET NAMES utf8mb4;;脚本批量执行时,这行必须是文件首行 - 更可靠方式:启动客户端时加参数
mysql --default-character-set=utf8mb4 -u root -p,避免依赖会话设置
存储过程中动态 SQL 拼接中文导致查询失败
用 CONCAT() 拼 WHERE name = ' + @name + ' 时,@name 是中文变量,但拼接过程按 character_set_connection 编码处理,极易产生 Mojibake。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 现象:过程内
SELECT返回空,但把相同 SQL 拷到客户端手动执行却能查到 - 根本原因:
CONCAT不自动转码,它直接按当前连接字符集拼字节流 - 安全写法:用
CONVERT(@name USING utf8mb4)包裹变量再拼接,例如CONCAT('WHERE name = ''', CONVERT(@name USING utf8mb4), '''') - 更优解:放弃字符串拼接,改用
PREPARE stmt FROM 'SELECT * FROM t WHERE name = ?'; EXECUTE stmt USING @name;,完全规避编码转换问题
过程调用时返回中文,但应用层收到乱码
过程本身没问题,SELECT '你好' 在 MySQL 客户端里显示正常,但 Java/Python/PHP 调用后拿到的是 或问号——说明断点在驱动或连接配置。
- 排查顺序:先在 mysql 命令行里
CALL your_proc();确认结果正确 → 再查应用连接串 - JDBC 必须带
useUnicode=true&characterEncoding=utf8mb4,漏掉useUnicode=true会导致characterEncoding不生效 - Python pymysql 需显式传
charset='utf8mb4'参数,connect()时不传等于用默认 latin1 - PHP mysqli 必须在
mysqli_connect()后立刻调用mysqli_set_charset($conn, 'utf8mb4'),晚一步都不行
WHERE 条件中显式 COLLATE 导致索引失效甚至报错 1267
过程里写 WHERE ref_id = _utf8mb4'xxx' COLLATE utf8mb4_unicode_ci,而 ref_id 列实际是 utf8 字符集 —— 表面看都是 utf8mb4,实则触发隐式转换与 collation 冲突。
- 后果分两级:轻则全表扫描(性能暴跌),重则直接报
Error 1267 Illegal mix of collations - 验证方法:查
INFORMATION_SCHEMA.COLUMNS,确认ref_id的character_set_name和collation_name - 安全写法:去掉
COLLATE,只写WHERE ref_id = _utf8mb4'xxx',让 MySQL 自动按列规则推导 - 根治方案:统一整张表为
utf8mb4,执行ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
最容易被跳过的其实是连接初始化那一步——SET NAMES utf8mb4 看似简单,但它必须发生在任何 DDL/DML 之前,且不能被任何中间件、ORM 或连接池覆盖。一旦过程定义已损坏,删重建是唯一办法,没有“在线修复”这种操作。

















