MySQL中如何设置存储过程的字符集避免中文乱码报错

小辰君_9671

小辰君_9671

2026-10-05

734人浏览

原创

必须在create procedure前执行set names utf8mb4,因中文字符串在客户端发送时即按character_set_client解析并固化进mysql.proc表,若为latin1或utf8mb3则存入即损坏,后续任何配置修改均无法修复。

mysql中如何设置存储过程的字符集避免中文乱码报错

CREATE PROCEDURE 前必须执行 SET NAMES utf8mb4

存储过程里的中文字符串(比如 SELECT '你好'、COMMENT '日志记录')是在客户端发送 SQL 时就被解析并固化进 mysql.proc 表的。如果此时 character_set_client 是 latin1 或 utf8(即 utf8mb3),MySQL 会把 UTF-8 编码的汉字字节按错误编码解释,存进去就是损坏数据——后续改任何配置都救不回来。

实操建议:

  • 在执行 CREATE PROCEDURE 语句前,**显式加一行**:SET NAMES utf8mb4;
  • 命令行导入脚本时,这行必须是第一行,不能靠 my.cnf 自动生效
  • 用 Navicat / Workbench 等 GUI 工具时,检查连接属性里是否启用了「使用 UTF8MB4」或手动执行该语句后再建过程
  • 避免在过程中临时切字符集,比如 SET character_set_results = latin1;,会污染后续输出

my.cnf 必须同时配 [client]、[mysql]、[mysqld] 三段

只在 [mysqld] 段写 character-set-server = utf8mb4 是无效的。它只影响新建库/表的默认值,不影响客户端怎么连进来——而存储过程创建依赖的是「连接发起时」的字符集。

三段作用差异:

  • [client]:控制所有客户端工具(mysql、mysqldump)的默认字符集
  • [mysql]:专用于 mysql 命令行客户端,优先级高于 [client]
  • [mysqld]:服务端行为,需同步设 collation-server = utf8mb4_unicode_ci 避免排序异常

Linux 下典型配置(/etc/my.cnf):

MySQL
MySQL

编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。

下载
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

改完必须 systemctl restart mysqld,reload 不生效。

存储过程体内部要声明 CHARACTER SET utf8mb4

即使连接层和建库建表都对了,过程体内的局部变量、临时表、字符串拼接仍可能因隐式转换出问题。MySQL 允许在 CREATE PROCEDURE 语句中显式声明字符集,语法位置敏感:

  • CHARACTER SET utf8mb4 必须放在 COMMENT 和 LANGUAGE SQL 之间
  • COLLATE utf8mb4_unicode_ci 虽非强制,但建议加上,避免与字段校对规则不一致引发隐式转换警告
  • 该声明会影响过程内所有未显式指定字符集的字符串常量、局部变量和临时表字段

示例片段:

CREATE PROCEDURE log_action(
  IN p_user_id INT,
  IN p_action VARCHAR(100)
)
COMMENT '记录用户操作'
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci
LANGUAGE SQL
BEGIN
  INSERT INTO user_log (user_id, action_desc) 
  VALUES (p_user_id, CONCAT('用户执行了:', p_action));
END

验证过程体是否真按 utf8mb4 加载

SHOW CREATE PROCEDURE 只显示原始定义语句,看不出中文是否被正确解析。真正要确认,得看运行时行为:

  • 调用后查结果字段是否为问号或 Mojibake(如 我们)
  • 过程里用 SELECT '测试中文' INTO @tmp; 再 SELECT @tmp;,观察输出
  • 检查 information_schema.routines 中 routine_definition 字段内容是否已乱码(说明创建时就坏了)

最容易被忽略的是:**过程一旦创建失败或部分损坏,不能靠 ALTER 修改,必须 DROP 后重建,并确保重建全程都在 utf8mb4 连接上下文中进行。**

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

4003

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

851

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1049

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

5861

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

2783

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

5840

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

7761

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1050

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

932

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL vs MySQL
PostgreSQL vs MySQL

共1课时 | 178人学习

使用phpenv集成环境安装极致CMS
使用phpenv集成环境安装极致CMS

共2课时 | 285人学习