Navicat连ClickHouse中文显示问号或方块的根本原因是连接未显式声明UTF-8编码,需在连接字符串中添加?charset=UTF-8(JDBC)或&charset=UTF-8(ODBC/原生),并确保驱动版本支持(clickhouse-jdbc 0.3.2+),同时SQL编辑器编码设为UTF-8。
Navicat 连 ClickHouse 中文显示问号或方块?先看连接层编码
根本原因不是 clickhouse 服务端没设 utf8,而是 navicat 建立连接时没告诉 clickhouse:“我要用 utf-8 传数据”。clickhouse 默认按 utf-8 解析,但 navicat 的 jdbc 或原生协议连接若未显式声明编码,会 fallback 到系统 locale(比如 windows 上是 gbk),导致握手阶段就错位。
实操建议:
- 在 Navicat 新建或编辑 ClickHouse 连接时,点开 高级 选项卡 → 找到
Connection String(连接字符串)输入框 - 在已有参数后追加:
?charset=UTF-8(JDBC 驱动)或&charset=UTF-8(ODBC/原生协议,视驱动而定) - 如果用的是
clickhouse-jdbc(推荐),完整示例:jdbc:clickhouse://127.0.0.1:8123/default?charset=UTF-8&useUnicode=true - 改完务必点 测试连接,不是只保存——很多乱码问题改了不重连根本无效
ClickHouse 服务端的 charset 配置其实不控制客户端通信
很多人去翻 /etc/clickhouse-server/config.xml,想找 <charset> 或类似字段,白忙。ClickHouse 本身没有“服务端字符集开关”这种设计:它只认字节流,只要客户端发来的是合法 UTF-8 字节,它就存;返回时也原样发回。所谓“服务端编码”其实是客户端和协议的事。
真正要检查的只有两处:
-
SELECT * FROM system.settings WHERE name LIKE '%charset%'—— 结果为空才正常,有值反而可能被旧配置误导 -
SHOW CREATE TABLE查表 DDL,确认ENGINE后没带奇怪的CHARSET=xxx(ClickHouse 表引擎不支持这个语法,写了会报错) - 如果用
MySQL 兼容模式接入(比如通过mysql_port),需额外确认mysql_port对应的tcp_port配置里没启用skip_utf8_check(默认关着,别动)
INSERT 中文数据进不去?重点查 Navicat 的 SQL 执行模式
即使连接字符串加了 charset=UTF-8,在 Navicat 里直接写 INSERT INTO t VALUES ('中文') 仍可能失败,错误信息常是:Code: 62. DB::Exception: Cannot parse string... 或更隐蔽的截断(只存前几个字)。
这是因为 Navicat 默认用“语句执行”而非“脚本执行”,对非 ASCII 字符的编码处理不稳定。解决方式很具体:
- 写 INSERT 语句时,右键编辑器 → 选 编码 → UTF-8(不是 UTF-8-BOM)
- 或者换用
INSERT ... SELECT绕过:比如先CREATE TEMPORARY TABLE tmp AS SELECT '中文' AS s,再INSERT INTO real_table SELECT * FROM tmp - 终极稳妥法:用
VALUES插入时,把中文转成 Unicode 转义,例如'\u4f60\u597d'(“你好”),ClickHouse 原生支持,且完全避开客户端解码环节
Navicat 版本和驱动版本不匹配会静默丢编码参数
Navicat 15 早期版(如 15.0.22)用的 clickhouse-jdbc 是 0.2.6,根本不识别 charset 参数;Navicat 16+ 默认带 0.3.2+,才真正支持。你填了 ?charset=UTF-8,但它压根不往连接里传。
验证和修复步骤:
- 打开 Navicat → 帮助 → 关于 → 看底部驱动版本,如果是
clickhouse-jdbc 0.2.x,必须升级 Navicat 或手动替换驱动 jar(路径通常在Navicat Premium.app/Contents/Frameworks/jdbc/或 Windows 下安装目录的drivers子目录) - 替换时注意:新 jar 必须和 Navicat 架构一致(x64 / ARM64),否则启动报
UnsatisfiedLinkError - 换完重启 Navicat,再连一次,执行
SELECT client_info(),返回结果里interface字段应为HTTP或TCP,且无乱码字样
最麻烦的不是设错,而是设了以为生效、其实被老驱动吞掉了——这点容易被忽略。

















