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

使用C嵌入式SQL从Ingres通过SQLDA获取整数/长整数异常问题

问题分析与解决方案

你遇到的核心问题是没有正确解析SQLDA中二进制存储的整数类型,而是把它们当成ASCII字符或单字节数据来处理了。Ingres的SQLDA里,数值类型(int、long等)是以二进制形式存储的,不是人类可读的ASCII,直接按char数组打印或者只取第一个字节转long肯定会出问题。

具体错误点

  1. 错误的打印/解析方式:你直接遍历sqldata的char字节并打印,还通过*sqlda->sqlvar[i].sqldata把第一个字节转成long——这只对1字节的极小整数有效,2字节/4字节的整数是多字节连续存储的二进制值,必须按对应的数据类型整体解析。
  2. 未利用sqltype字段判断类型:SQLDA的sqlvar[i].sqltype字段明确标记了该列的数据类型,你需要根据这个类型来选择对应的解析方式,而不是统一按char处理。

修正后的代码示例

首先确保你包含了Ingres的SQLDA头文件:#include <iisqlda.h>,然后修改FETCH后的解析循环:

EXEC SQL FETCH csr0 USING DESCRIPTOR sqlda;
for( i=0; i<sqlda->sqld; i++) {
    printf("Column %d | Type: %d | Length: %d | ", i+1, sqlda->sqlvar[i].sqltype, sqlda->sqlvar[i].sqllen);
    
    // 根据字段类型解析二进制数据
    switch(sqlda->sqlvar[i].sqltype) {
        case IIAPI_SMALLINT_TYPE: // 2字节短整数
            if (sqlda->sqlvar[i].sqllen == sizeof(short)) {
                short small_val = *(short*)sqlda->sqlvar[i].sqldata;
                printf("Value: %hd", small_val);
            }
            break;
        case IIAPI_INT_TYPE: // 4字节整数(对应C的int/long,取决于平台)
            if (sqlda->sqlvar[i].sqllen == sizeof(int)) {
                int int_val = *(int*)sqlda->sqlvar[i].sqldata;
                printf("Value: %d", int_val);
            }
            break;
        case IIAPI_CHAR_TYPE: // 字符串类型
            // 如果是VARCHAR类型,前2字节是长度,需要跳过
            if (sqlda->sqlvar[i].sqltype == IIAPI_VARCHAR_TYPE) {
                printf("Value: %s", sqlda->sqlvar[i].sqldata + 2);
            } else {
                printf("Value: %s", sqlda->sqlvar[i].sqldata);
            }
            break;
        default:
            printf("Unsupported data type");
            break;
    }

    // 检查是否为NULL值(sqlind为-1表示空)
    if (*sqlda->sqlvar[i].sqlind == -1) {
        printf(" (NULL)");
    }
    printf("\n");
}

关键注意事项

  1. 类型匹配:Ingres的类型常量(如IIAPI_SMALLINT_TYPE)定义在iisqlda.h中,要确保你引用的常量和实际返回的sqltype一致——如果不确定,可以先打印sqlvar[i].sqltype的值,对照Ingres文档确认对应的类型。
  2. 字节序问题:通常嵌入式SQL的SQLDA会使用主机字节序,直接强制类型转换即可;如果遇到数值颠倒的情况,可能需要用ntohs()(针对2字节)或ntohl()(针对4字节)进行字节序转换。
  3. 字符串截断问题:你提到字符串被截断2字节,大概率是因为该字段是VARCHAR类型——Ingres的VARCHAR会在sqldata的前2字节存储字符串长度,后面才是实际字符,所以需要跳过前2字节才能拿到完整字符串。

补充说明

你的SQLDA分配代码里(longs+ints+strings)这个变量看起来没定义,虽然程序能运行,但建议直接用列数(这里是5)来计算分配大小,避免潜在的错误:

sqlda = (IISQLDA *)calloc(1, IISQDA_HEAD_SIZE + (5 * IISQDA_VAR_SIZE));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:40:27