根本原因是客户端(navicat)与服务端(postgresql)字符集协商失败,需确保数据库编码为utf8、连接字符串添加options=-c%20client_encoding%3dutf8、sql编辑器设为utf-8、导出csv选utf-8 with bom,并避免使用无效的alter database set client_encoding。
乱码不是字体问题,也不是“重新选个编码”就能解决的——根本原因是客户端(navicat)和服务端(postgresql)在字符集协商上断开了,字节流发过去,对方按错的规则解,自然显示为?或方块。
确认数据库实际编码是不是UTF8
别信 Navicat 界面里显示的“编码:UTF-8”,得查服务端真实值:
- 在 Navicat 查询窗口执行:
SELECT pg_encoding_to_char(encoding) FROM pg_database WHERE datname = current_database(); - 必须返回
UTF8;如果返回SQL_ASCII、GBK或其他,说明数据库本身不是 UTF-8,此时调客户端毫无意义,得重建库或迁移数据 - PostgreSQL 一旦初始化为非 UTF-8 编码,无法在线修改,硬改
ALTER DATABASE ... SET client_encoding是无效操作
连接字符串里必须加 URL 编码后的 client_encoding 参数
Navicat 的「高级」页里勾选「运行前执行命令」并填 SET client_encoding TO 'UTF8';,看似有效,但容易被忽略两点:一是该命令只对当前会话生效,二是某些连接模式(如复用连接池)可能绕过它。最稳的方式是直接塞进连接串:
- 打开连接编辑页 → 切到「SSH/SSL」标签 → 找到「连接字符串」输入框
- 在已有内容末尾追加:
options=-c%20client_encoding%3DUTF8(注意空格和等号都已 URL 编码) - 保存后重连,再执行
SHOW client_encoding;,结果必须是UTF8,否则参数没生效 - 不要写成
options=-c client_encoding=UTF8—— 未编码的空格会导致连接失败
Navicat SQL 编辑器默认用系统 ANSI 编码读文件
新建查询窗口里打中文变空格、粘贴中文后存盘再打开全乱,大概率是编辑器本身没设对编码,跟数据库无关:
- 关闭所有查询窗口 → 「工具」→「选项」→「外观」→「SQL 编辑器」
- 「字体」选支持中文的(如
Microsoft YaHei或Consolas),「编码」下拉框务必手动选UTF-8(不是Auto,也不是GBK) - 别依赖「自动检测编码」——它常把带 BOM 的 UTF-8 当 GBK 解,一保存就毁数据
- 改完重启 Navicat,新建窗口先执行
SHOW client_encoding;确认双保险
导出 CSV 含中文,Excel 打开全是乱码
这不是 PostgreSQL 或 Navicat 的 bug,是 Excel 的设计缺陷:Windows 版 Excel 默认用系统编码(GBK)打开无 BOM 的 UTF-8 文件:
- Navicat 导出时,「编码」选
UTF-8 with BOM(不是单纯的UTF-8) - 如果导出后仍乱码,检查 Excel 是否开了「数据」→「从文本/CSV」导入,选 UTF-8 + 自动检测分隔符,比双击打开可靠得多
- Linux/macOS 用户用 LibreOffice 或 VS Code 打开 CSV 更省心,它们默认识别 UTF-8 无 BOM
最容易被忽略的是:即使所有配置都对了,只要 Navicat 连接时用了 Windows 默认区域设置(如简体中文 → GBK),而 PostgreSQL 运行在 Linux 上,协议层字节解释就会错位——这种乱码不会报错,INSERT 看似成功,SELECT 出来却是问号,排查起来极隐蔽。











