如何正确获取编码正常的带重音字符
编码异常修复方案
核心问题定位
当前编码错乱是多层字符集配置不一致导致的:
- 数据库级默认字符集为
latin1,虽然单表设置了utf8默认字符集,但连接层未显式指定字符集时会继承库级配置,触发转码错误 - 不同客户端连接字符集不统一:DataGrip自带字符集容错转码,将错存的重音字符
ó替换为普通o显示为Soni属于假象,并非数据存储正确;命令行mysql客户端未做兼容转码,无法识别非法多字节字符直接显示为�;程序端拿到的S\u00f3ni(对应Sóni)说明程序侧字符集输出逻辑正常,问题出在数据库存储链路。
分步修复操作
1. 固定数据库连接字符集
不要依赖数据库、表的默认字符集配置,在代码层建立数据库连接时显式指定字符集,优先使用utf8mb4(MySQL原生utf8是3字节阉割版本,无法支持emoji和部分生僻特殊字符):
- PDO连接示例,直接在DSN中声明charset参数:
$pdo = new PDO('mysql:host=127.0.0.1;dbname=dbname;charset=utf8mb4', '用户名', '密码');
- MySQLi连接示例,连接后调用驱动方法设置字符集:
$mysqli = new mysqli('127.0.0.1', '用户名', '密码', 'dbname'); $mysqli->set_charset('utf8mb4');
不要通过执行SET NAMES utf8的SQL语句设置字符集,驱动层自带的设置方法会同时完成字符转义逻辑的适配,比手动执行SQL更可靠。
2. 修正库、表、字段的字符集配置
首先修改库级默认字符集,避免后续新建表继承错误的latin1配置:
ALTER DATABASE dbname CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
再修改目标表及表内所有字段的字符集,命令执行时会自动转换已有存量数据,执行前务必备份表数据,避免存量乱码数据二次转码损坏:
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
3. 修复命令行MySQL客户端显示问题
临时生效可在登录客户端后执行以下语句设置当前连接字符集:
SET NAMES utf8mb4;
永久生效需修改MySQL配置文件:
- Linux环境修改
my.cnf,Windows环境修改my.ini,在对应配置段添加以下内容:
[client] default-character-set = utf8mb4 [mysql] default-character-set = utf8mb4 [mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_general_ci
修改完成后重启MySQL服务即可。
4. 结果验证
重新插入带重音字符的测试数据,分别在程序端、DataGrip、命令行mysql客户端查询,三个端统一显示正确的Sóni即为修复完成。
内容的提问来源于stack exchange,提问作者Mario
相关产品推荐
相关产品推荐

