【问题描述】

在 GBK 编码的 YashanDB 数据库中,尝试将包含生僻字的人名插入到 nvarchar2 字段时,出现了乱码或字符丢失的现象。例如以下操作:

CREATE TABLE t1 (id INT, c1 NVARCHAR2(128));
INSERT INTO t1 VALUES (1. '粼');  -- 粼 为生僻字

插入成功后,在客户端显示为乱码或问号(?)。

image.png
image.png

【问题版本】

YashanDB 23.2.4.14 及之前版本

【问题成因】

  1. GBK 编码不支持生僻字

GBK 字符集本身对某些生僻汉字不具备编码能力。在终端输入这些字符时,编码器无法完成字符转换,导致实际传入数据为乱码或缺失。

  1. 客户端与服务端编码不一致

当客户端编码为 UTF-8.YashanDB 服务端编码为 GBK,yasql 会尝试将 UTF-8 转换为 GBK。此时如果输入了 GBK 无法识别的字符,转换将失败,表现为:

数据存入前已被替换为问号(0x3F);

nvarchar2 类型在服务端最终被误转为错误的 utf16 编码。
image.png

image.png
【典型现象】

插入生僻字后,在查询时显示为乱码;

使用 exp 导出数据时报错,如:

YAS-00218 string conversion failed
某些空白字符在 GBK 中存在但 UTF-8 无法识别,导出时报错。
image.png

【解决方案】

方式一:确保客户端和服务端编码一致

最关键的一点是:yasql客户端编码要与终端编码一致,建议设置为 UTF-8.避免不必要的转码过程。

方式二:使用yasdb客户端 API 进行 UTF16 插入

YashanDB 提供的 yacBindParameter 接口支持传入 utf16 编码的参数,可直接插入生僻字,无编码转换问题。

方式三:数据库新建时选择 UTF8 编码(根本性解决)

若业务有大量生僻字、特殊字符使用需求,建议使用 UTF8 或 UTF8MB4 等更完整的字符集初始化数据库。

【编码转换机制说明】
image.png
image.png

插入(INSERT)流程:

终端(UTF8) → yasql(GBK) → 服务端(GBK) → 存储为 UTF16

若 yasql 与终端编码不一致,转换失败概率高,最终入库的 UTF16 编码是错误的。

查询(SELECT)流程:
`
服务端(UTF16) → yasql(GBK) → 终端(UTF8)`
只有终端与 yasql 保持编码一致,才能正常显示查询结果。

【推荐做法总结】

image.png


数据库砖家
1 声望0 粉丝