Pro * C - 获取数组?

时间:2014-02-21 15:02:29

标签: c oracle

我正在尝试使用Pro * C从游标中获取数组。

这样的事情:

struct array {
  char key[10]];
  char name[32];
};

struct array rows[250];

// Open cursor...

EXEC SQL FETCH my_cursor INTO :rows;

这样可行,但字段不是以空值终止的。我想这是因为我通常会使用:

EXEC SQL VAR key IS STRING(11);
EXEC SQL VAR name IS STRING(33);

但这似乎不适用于数组。

有谁知道如何解决这个问题?

谢谢!

1 个答案:

答案 0 :(得分:2)

这些值被视为(Oracle)CHAR,因为无法确定长度。由于它是fixed size,因此用空格填充值是正常的。

使用虚拟表:

create table t42 (key varchar2(10), name varchar2(32));
insert into t42 values ('abc','A B C');
insert into t42 values ('def','D E F');
commit;

此代码:

#include <string.h>
#include <stdio.h>

exec sql include sqlca.h;

int main(int argc, char **argv)
{
    VARCHAR v_userid[15];
    VARCHAR v_passwd[15];

    struct array {
        char key[10];
        char name[32];
    };

    struct array rows[2];

    strcpy(v_userid.arr, "user");
    v_userid.len = 5;
    strcpy(v_passwd.arr, "password");
    v_passwd.len = 8;

    exec sql connect :v_userid identified by :v_passwd;
    if (sqlca.sqlcode != 0)
    {
        printf("ORA%d: %s\n", sqlca.sqlcode, sqlca.sqlerrm);
        return(1);
    }

    memset(rows, '\0', sizeof(rows));
    EXEC SQL DECLARE cur CURSOR FOR select * from t42;
    EXEC SQL OPEN cur;
    EXEC SQL FETCH cur INTO :rows;
    printf("%d\n", sqlca.sqlcode);
    printf("<%s><%s>\n", rows[0].key, rows[0].name);
    printf("<%s><%s>\n", rows[1].key, rows[1].name);
    EXEC SQL CLOSE cur;
}

...显示您描述的相同行为:

0
<abc      ><A B C                          >
<def      ><D E F                          >

在获取数据时,你实际上是在进行隐式cast(key as char(10)),这会引入填充,因为它知道它会进入CHAR而不是VARCHAR变量。

将数组成员更改为VARCHAR data types(包括引用.arr成员):

#include <string.h>
#include <stdio.h>

exec sql include sqlca.h;

int main(int argc, char **argv)
{
    VARCHAR v_userid[15];
    VARCHAR v_passwd[15];

    struct array {
        VARCHAR key[10];
        VARCHAR name[32];
    };

    struct array rows[2];

    strcpy(v_userid.arr, "user");
    v_userid.len = 5;
    strcpy(v_passwd.arr, "password");
    v_passwd.len = 8;

    exec sql connect :v_userid identified by :v_passwd;
    if (sqlca.sqlcode != 0)
    {
        printf("ORA%d: %s\n", sqlca.sqlcode, sqlca.sqlerrm);
        return(1);
    }

    memset(rows, '\0', sizeof(rows));
    EXEC SQL DECLARE cur CURSOR FOR select * from t42;
    EXEC SQL OPEN cur;
    EXEC SQL FETCH cur INTO :rows;
    printf("%d\n", sqlca.sqlcode);
    printf("<%s><%s>\n", rows[0].key.arr, rows[0].name.arr);
    printf("<%s><%s>\n", rows[1].key.arr, rows[1].name.arr);
    EXEC SQL CLOSE cur;
}

...让它按预期工作:

0
<abc><A B C>
<def><D E F>

当然有一个错误(好吧,至少有一个!)我故意留下了。如果我的数据库字段是10和32个字符,那么VARCHAR元素的大小 - 或原始的char元素 - 需要大一个字节来保存终止空值 - 这是当然基本的C东西,所以你的真实列完全可能分别是9和31个字符(尽管你的EXEC SQL VAR示例表明没有)。我有这样的组合,如果我:

insert into t42 values ('1234567890','12345678901234567890123456789012');

...然后第三行显示为:

<1234567890 ><12345678901234567890123456789012@>

...因为它正在读取已分配的空间。当然,如果我制作结构VARCHAR key[11]; VARCHAR name[33];,则按预期工作。