版本号检测导致无法操作数据库

使用 knex 以 PostgreSQL 模式连接数据库时,如果没有指定版本号,knex 会报错导致 Node.JS 程序终止。

原因分析

使用 knex 连接数据库时,如果没有指定版本号,knex 会主动进行检测,但由于 KES 中 select version() 返回的格式与 PostgreSQL 不同,导致 knex 报错。

CleanShot 2025 02 27 at 12.25.33@2x
图 1. knex 用 PostgreSQL 模式连接时会预期查询结果中带有 PostgreSQL 字符串

knex 希望返回结果中包含 PostgreSQL 字符串

CleanShot 2025 02 27 at 12.44.57@2x
图 2. PostgreSQL 数据库中的查询结果

但是 KES 中实际返回结果不包含该字符串

CleanShot 2025 02 27 at 12.43.28@2x
图 3. KingbaseES V9 数据库中的查询结果

解决方式

在 knex 的连接配置中通过 version 参数指定版本,可以避免上述的检测过程,从而实现正常使用。

CleanShot 2025 02 27 at 12.47.56@2x
图 4. 在配置项中明确指定 version

设置为 not null 的字段无法插入空字符串

尝试往设置为 not null 的 description 字段插入空字符串时,数据库提示违反非空约束,且返回的详情中把 description 位置的空字符串显示成了 null

原因分析

KES 内部将空字符串认作了 null

CleanShot 2025 02 27 at 12.58.05@2x
图 5. 往 description 字段插入空字符串,提示违反 not-null 约束

经查询资料确定,通过容器方式运行 KES 时,默认启用 Oracle 兼容模式,并开启 ora_input_emptystr_isnull 参数,此时在插入或查询时空字符和 null 都会被当作 null。

解决方式1

修改兼容模式,可以用 set ora_iput_emptystr_isnull = no 单独修改本参数,也可以直接将整个数据库调整为 PG 兼容模式,为了避免以后遇到更多的兼容问题,我直接将整个容器销毁,并以 PG 兼容模式重新创建。

CleanShot 2025 02 27 at 14.03.45@2x
图 6. 以 PG 兼容模式重新创建容器

这里需要主要,通过 DB_MODE=pg 以 PG 兼容模式启动数据库时,必须同时添加参数 ENABLE_CI=no ,否则数据库无法正常启动

解决方式2

如果数据库环境无法控制,建议修改数据库中的表定义,让字符串字段允许 null,同时程序中做好检查避免使用空字符串,没有数据时一律使用 null,从程序本身的层面来确保对两种不同行为方式数据库的兼容性。

如过程序本身没有非要区分 null 和空字符串的需求,建议即使已经采用了方案1,也同时采用方式2的原则,提高程序的兼容性。