字符集转换是什么
字符集转换用在两处:把二进制(BLOB / bytea)里的字节按指定字符集解码成字符串,或者在字符串的不同字符集之间转换,以便比较与写入。MySQL 提供 CONVERT(expr USING charset),PostgreSQL 用 convert_from / convert_to / convert(bytea, 源, 目标)。排查中文乱码基本围绕三点:字节实际的编码是什么、连接的字符集是什么、列与表的字符集是什么,三者只要有一处不一致就会出现乱码。
基本信息
| MySQL 字符集转换 | CONVERT(str USING utf8mb4)、CONVERT(str USING binary) |
|---|---|
| MySQL 类型转换 | CONVERT(str, CHAR) 是类型转换,与 USING 写法只差一个逗号,务必区分 |
| PostgreSQL | convert_from(bytea, 'UTF8')、convert_to(text, 'UTF8')、convert(bytea, 'LATIN1', 'UTF8') |
| 连接层参数 | MySQL 看 character_set_client / connection / results;PostgreSQL 看 client_encoding |
| 转换失败 | MySQL 报错或截断,PostgreSQL 报 invalid byte sequence for encoding |
典型使用场景
- BLOB 里存的其实是文本,需要按指定字符集解码出来查
- 修复历史乱码:utf8 字节被当成 latin1 存进列
- 比较两个不同字符集的列,先把一侧转换到同一字符集
- 生成指定编码的导出数据,交给下游系统
- 排查「同一条数据在应用里正常、在客户端工具里乱码」
MySQL 用法
MySQL 用法
# 修复乱码:utf8 字节被当成 latin1 存储,需要双向转换回来
SELECT CONVERT(BINARY CONVERT(name USING latin1) USING utf8mb4) AS fixed_name
FROM users WHERE id = 1;
# BLOB 里的文本按 utf8mb4 解码
SELECT CONVERT(blob_col USING utf8mb4) AS text_col FROM logs LIMIT 1;
# 确认当前连接相关的字符集,乱码排查第一步
SHOW VARIABLES LIKE 'character_set%';PostgreSQL 用法
PostgreSQL 用法
-- 字节转文本 / 文本转字节
SELECT convert_from(data, 'UTF8') AS text_col FROM logs;
SELECT convert_to('中文', 'UTF8') AS bytes;
-- 从一种编码转换到另一种(参数为 字节、源编码、目标编码)
SELECT convert(data, 'LATIN1', 'UTF8') AS text_col FROM logs;
-- 确认编码参数,避免客户端与服务端不一致
SHOW client_encoding;
SHOW server_encoding;常见目标与写法对照
| 目标 | MySQL | PostgreSQL |
|---|---|---|
| 字节按编码解码 | CONVERT(blob USING utf8mb4) | convert_from(bytea, 'UTF8') |
| 文本转字节 | CAST(str AS BINARY) | convert_to(text, 'UTF8') |
| 编码间转换 | CONVERT(str USING 目标字符集) | convert(bytea, 源, 目标) |
| 类型转换(非字符集) | CONVERT(str, CHAR) | CAST(str AS text) |
| 连接字符集 | character_set_client / connection / results | client_encoding |
MySQL 的 CONVERT 有两个重载:CONVERT(expr USING charset) 做字符集转换,CONVERT(expr, type) 做类型转换,写法只差一个逗号,混用会让结果完全不同。
修乱码先试算再落库:先复制数据或在 SELECT 里验证转换结果,确认正确后才 UPDATE。方向判断错误的双向转换会把数据彻底毁掉,无法靠再次转换还原。
排查顺序建议固定:先确认字节的实际编码,再看连接字符集,最后看列与表的字符集;跳过前两步直接改表字符集,常把「显示乱码」升级成「数据损坏」。