You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用odbc_connect查询IBM i数据库时部分字段乱码求助

Linux环境ODBC连接IBM i特定字段乱码问题解决

问题背景

本地使用PDO连接ODBC($odbcConnect = new PDO("odbc:$dsn", "$userid", "$password");)可正常获取所有字段,但生产环境为Linux,PDO无法工作,改用odbc_connect($odbcConnect = odbc_connect("Driver={IBM i Access ODBC Driver}; system=$mapics_server; uid=$mapics_username; pwd=$mapics_password", "Nothing", "Nothing");)后,CODE_FOURNISSEUR和NOM_FOURNISSEUR字段出现乱码(如b"õððùô÷"),其余字段数据正常。

关联查询语句示例:

SELECT * FROM 
        (
            SELECT 
                as numero_commande,
                as code_article,
                as mpn,
                as code_cadence,
                as code_fournisseur,
                as nom_fournisseur,
                as date_besoin,
                ROW_NUMBER() OVER (ORDER BY  desc) AS Rank
            FROM
                amflib6. as POI
                JOIN  as V on  = 
                JOIN  as O on  = 
            WHERE " . implode(" AND ", $parametres) . "
        ) X WHERE Rank BETWEEN " . $premier . " AND " . $deuxieme;

原执行代码存在逻辑问题(混合使用预处理与直接执行):

$rows = array();
$stmt = odbc_prepare($odbcConnect, $queryPrepare);
if (odbc_execute($stmt, $dataParams)) {
    $result = odbc_exec($odbcConnect, $query);
    while($row = odbc_fetch_array($result)) {
        dump($row);
        $rows[] = $row;
    }
} else {
    dump("AHHHHHHHHHHHHH");
    return [];
}
odbc_close($odbcConnect);

解决方法

1. 调整ODBC连接字符串的CCSID参数

IBM i数据库使用CCSID标识字符集,在连接字符串中指定对应编码的CCSID(如UTF-8对应1208),强制驱动转换字符集:

$odbcConnect = odbc_connect(
    "Driver={IBM i Access ODBC Driver}; system=$mapics_server; uid=$mapics_username; pwd=$mapics_password; CCSID=1208", 
    "Nothing", 
    "Nothing"
);

常见CCSID对应:

  • 1208:UTF-8
  • 37:EBCDIC(美国英语)
  • 500:EBCDIC(国际通用)
    需根据数据库实际使用的字符集选择对应CCSID。

2. 手动转换字段编码

若连接参数调整无效,可在获取数据时手动将EBCDIC编码转成UTF-8:

while($row = odbc_fetch_array($result)) {
    // 转换乱码字段
    if(isset($row['CODE_FOURNISSEUR'])) {
        $row['CODE_FOURNISSEUR'] = iconv('IBM-1047', 'UTF-8', $row['CODE_FOURNISSEUR']);
    }
    if(isset($row['NOM_FOURNISSEUR'])) {
        $row['NOM_FOURNISSEUR'] = iconv('IBM-1047', 'UTF-8', $row['NOM_FOURNISSEUR']);
    }
    $rows[] = $row;
}

注:IBM-1047是IBM i常用的EBCDIC编码,若数据库使用其他EBCDIC编码,替换为对应值(如IBM-500)。

3. 修正查询执行逻辑

原代码混合使用odbc_prepare/odbc_execute和odbc_exec属于错误用法,需统一逻辑:

正确使用预处理查询

$rows = array();
$stmt = odbc_prepare($odbcConnect, $queryPrepare);
if (odbc_execute($stmt, $dataParams)) {
    while($row = odbc_fetch_array($stmt)) {
        // 按需添加转码逻辑
        if(isset($row['CODE_FOURNISSEUR'])) {
            $row['CODE_FOURNISSEUR'] = iconv('IBM-1047', 'UTF-8', $row['CODE_FOURNISSEUR']);
        }
        if(isset($row['NOM_FOURNISSEUR'])) {
            $row['NOM_FOURNISSEUR'] = iconv('IBM-1047', 'UTF-8', $row['NOM_FOURNISSEUR']);
        }
        $rows[] = $row;
    }
} else {
    dump("查询执行失败");
    return [];
}
odbc_close($odbcConnect);

4. 检查Linux ODBC驱动配置

确认Linux上的IBM i Access ODBC驱动为最新版本,或在odbcinst.ini中配置默认CCSID:

[IBM i Access ODBC Driver]
Description=IBM i Access ODBC Driver
Driver=/opt/ibm/iaccess/lib/libcwbodbc.so
Setup=/opt/ibm/iaccess/lib/libcwbodbcs.so
Driver64=/opt/ibm/iaccess/lib64/libcwbodbc.so
Setup64=/opt/ibm/iaccess/lib64/libcwbodbcs.so
FileUsage=1
CCSID=1208

内容的提问来源于stack exchange,提问作者Jacques Pirault

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 01:36:01