在使用 PHP 通过 ODBC 访问 YashanDB 数据库时,有用户反馈:查询字段长度超过 256 字节的数据时,结果显示被截断。这个问题看似奇怪,但其实和 ODBC 接口的行为密切相关。本文将带你全面分析原因,并提供实用的规避方案。
image.png

一、问题现象

使用 PHP 的 PDO_ODBC 查询 YashanDB 表中某字段 c1.如果其长度超过 256 字节,结果会被截断;

使用 isql 工具执行相同 SQL,也无法完整显示超过 300 字节的数据;

但在 MySQL 或 Oracle 中同样语句执行正常,显示完整数据。

image.png
二、影响范围

问题出现于 YashanDB 23.2.4.14 及以下版本;

涉及 ODBC 驱动与isql 工具的默认数据读取逻辑。

image.png
三、问题根因分析

  1. ODBC 驱动行为限制

当前版本的 YashanDB ODBC 驱动接口 SQLGetData 仅支持一次性获取数据;

而 PHP 的 PDO_ODBC 实现,默认每次只取 256 字节,超出部分需通过多次 SQLGetData 调用获取;

由于 YashanDB 还不支持多次取数,导致超长字符串显示被截断。
image.png

  1. isql 工具本身限制

isql 工具中 SQLGetData 默认最多返回 300 字节内容;

超过部分会被直接省略,因此你在终端中也看不到完整内容。

image.png
四、解决方案与绕过方式

image.png
方案一:更换 PHP 扩展为ODBC

改用 PHP 的原生 ODBC 扩展库(而非 PDO_ODBC),因为它会一次性读取整列数据。示例如下:


function odbc_php_exe() {
    echo "开始测试\n";
    $conn = odbc_connect("Yashandb", "sys", "yasdb_123");
    if (!$conn) {
        exit("连接失败");
    }
    $sql = "select c1, c2 from test062";
    $rs = odbc_exec($conn, $sql);
    while (odbc_fetch_row($rs)) {
        $c1 = odbc_result($rs, "c1");
        $c2 = odbc_result($rs, "c2");
        echo "c1: $c1\n";
        echo "c2: $c2\n";
    }
    odbc_close($conn);
    echo "测试结束\n";
}
odbc_php_exe();

方案二:修改 isql 源码并重新编译

image.png
如果你希望 isql 工具支持超过 300 字节的显示,可以:

修改其源码中 SQLGetData 对数据长度的限制逻辑;

改成“循环获取”或“一次性读取全部数据”;

然后重新编译生成 isql 执行文件。

这样,isql 就能完整展示长字段内容。

五、排查经验分享

查看 odbc.log 文件,发现 PDO_ODBC 的默认 buffer 为 256 字节;

而 isql 的默认 buffer 为 300 字节;

image.png
image.png
对比两种 PHP 扩展取数逻辑后发现,PDO_ODBC 依赖多次调用 SQLGetData,而 ODBC 扩展则是一次性读取;

进一步确认:问题并非 PHP 自身限制,而是 YashanDB 当前 ODBC 驱动的实现行为。

六、结语

YashanDB 作为国产数据库中兼容性较好的代表,在多数场景中表现稳定,但在一些语言驱动兼容细节上仍在不断完善中。通过使用合适的方式(如更换 PHP 扩展)可以顺利规避问题,提升使用体验。


数据库砖家
1 声望0 粉丝