浅析 SQLCA及SQLDA

SQLCA的说明
    执行PRO*C程序时, ORACLE把每个SQL语句执行的状态信息存入到 SQLCA中, 这些信息包扩错误代码、警告标志、诊断正文和处理行数。因此返回的信息来检测SQL语句的执行情况。
SQLCA的组成
    PRO*C程序中的SQLCA时C语言中的一个结构变量, 组成为:
    struct sqlca 
    {
        char sqlcaid[8];
        long sqlcabc;
        long sqlcode;
        struct 
        {
            unsigned short sqlerrml;
            char sqlerrmc[70];
        } sqlerrm;
        char sqlerrp[8];
        long sqlerrd[6];
        char sqlwarn[8];
        char sqlext[8];
    };
    struct sqlca sqlca;

sqlcaid: 字符串字段, 被初始为sqlca, 用于标识SQL通信区。
sqlabc: 整型字段, 用于保留SQL通信区的字节长度。
sqlcode: 整型字段, 用于保留最近执行的SQL语句的状态:
    = 0  表示该SQL语句执行成功, 没有发生错误和异常。
    > 0  表示执行了该SQL语句, 但有一异常。
    < 0  表示由于DB、系统、网络或程序有错误, ORACLE 未执行该语句。如出现这类错误, 当前事务一般回退。
sqlerrm: 是个子结构, 含有两个元素。
    sqlerrmc: 字符串字段, 保存与sqlcode对应的正文, 用SQLGLM()函数引用。当sqlcode < 0时, 该正文表示当前SQL的执行情况; 如sqlcode = 0时, 该正文表示前面SQL的执行情况。
    sqlerrml: 整字段, 上述正文长度。
sqlerrd: 长整数组, 6个元素, 用了2个。
    sqlerrd[2]: 保存当前SQL语句处理的行数。但若当前SQL失败, 则无定义; 若在数组操作中出错, 则停于出错行, 这时给出成功处理的行数; OPEN执行后, 清为0, FECTH 后增值(原有值+上本次fetch的行数); EXECUTE、INSERT、UPDATE、SELETE和SELECT后, 为成功处理的行数。
    sqlerrd[4]: 指出语句中出错的位移, 首字符位移为0。
sqlwarn: 字符数组, 8个元素, 用了5个。
    sqlwarn[0]: 如为空, 无警告; 如为"W", 有警告;
    sqlwarn[1]: 如为 "W", 表示宿主变量宽度不够, 返回字符数据被截断; 对数字型数据截断无警告。为了决定何字段被截断及截了多少, 查相应指示变量, 该指示变量的正值是列的原长。
    sqlwarn[3]: 如为"W", 表示查询选择表中的列数不等于SELECT或FECTH的INTO子句的宿主变量数, 返回为两者中少者。
    sqlwarn[4]: 如为"W", 表示DELETE或UPDATE语句无WHERE限制条件, 提醒用户小心。
    sqlwarn[5]: 如为"W", 表示EXEC SQL CREATE {PROCEDURE | FUNCTION | PACKAGE | PACKAGE BODY}语句由于PL/SQL编译而失败
SQLCA说明
    MODE={ANSI13|ORACLE}, 要说明SQLCA; MODE={ANSI|ANSI14},SQLCA说明可选, 但必说明SQLCODE状态变量。说明方式可为:
    EXEC SQL INCLUDE sqlca;
    也可把上述sqlca代码直接编在程序中。
    一个PRO*C程序可说明多个SQLCA, 比如一全程 SQLCA, 几个局部SQLCA, ORACLE仅对活动的SQLCA返回信息。当 PRO*C由几个文件组成时, 在一源文件中定义一全局SQLCA, 另一源文件中说明为extern存储类, 其说明为:
    #define SQLCA_STORAGE_CLASS extern
    可用SQL_INIT初始化SQLCA; 如SQLCA说明为自变量, 可能不能用它初始SQLCA。

    ORACLE错误信息最大为512字节, 用SQLGLM可取出:
    main()
    { 
        char msg_buf[100]; /* buffer for message text */
        int buf_size = 100; /* size of buffer in bytes */
        int msg_len; /* length of message text */
        EXEC SQL WHENEVER SQLERROR GOTO sqlerror
        ...
        sqlerror: /* get full text of error massage. */ 
        sqlglm(msg_buf, &buf_size, &msg_len);
        /* Null_terminate and print the text. */
        msg_buf[msg_len] = '/0';
        printf("/n%s/n", msg_buf);
        ...
    }

 

 

未完待续。。

 

 

 

SQLDA 的结构如下:
struct SQLDA
{
    long  N;    /* Descriptor size in number of entries */
    char  **V;  /*Ptr to Arr of addresses of main variables */
    long  *L;   /* Ptr to Arr of lengths of buffers */
    short *T;   /* Ptr to Arr of types of buffers */
    short **I;  /* Ptr to Arr of addresses of indicator vars */
    long  F;    /* Number of variables found by DESCRIBE */
    char  **S;  /* Ptr to Arr of variable name pointers */
    short *M;   /* Ptr to Arr of max lengths of var. names */
    short *C;   /* Ptr to Arr of current lengths of var. names */
    char  **X;  /* Ptr to Arr of ind. var. name pointers */
    short *Y;   /* Ptr to Arr of max lengths of ind. var. names */
    short *Z;   /* Ptr to Arr of cur lengths of ind. var. names */
};
SQLDA结构成员作用描述:
名称 描述
N   SELECT-LIST列或占位符的最大数量,执行DESCRIBE前必须执行SQLSQLDAAlloc()函数给N进行赋值,设定描述数组的维数,其决定了描述字结构成员数组的最大元素个数。在DESCRIBE命令后,必须将存储在F中的变量真实个数赋值给N。
V   是一个指向一个地址数组的指针,在该数组中存储SELECT-LIST列值或绑定变量的值。当使用SQLSQLDAAlloc函数时,系统给V[0]到V[n-]赋值为0。在使用select descriptors时,必须在FETCH语句前,给V指针数组分配内存空间,应为下列语句要用到两种描述字具体的值:
    EXEC SQL FETCH ... USING ‘select descriptors’
    对于bind descriptors,必须在OPEN语句前分配空间
    EXEC SQL OPEN ... USING ‘bind descriptors’
L   L是一个指向存放select-list或bind-variable变量值长度数组的指针。对于selectdescriptors,DESCRIBE SELECT LIST语句设置数组中各元素的值,对不在select-list的对应长度设置成该类型的可的定义的最大长度。在FETCH语句前,用户可能需要重新修改变量长度,比如为了显示原因,需要将NUMBER类型数据存储到C语言char[]类型,就需要通过SQLNumberPrecV6()函数得到NUMBER长度,然后转换成字符串后的真实长度。对于bind descriptors,用户必须在OPEN语句前,给数组成员赋对应V变量成员长度的值。因为Oracle间接的通过使用存储在V[i]变量的地址访问数据区域,如果不指定L[i]变量,就不能得到V[i]的存储数据的长度,也就不能得到或给V[i]指定的数据区域赋值。如果用户需要更改V[i]指定数据区域的长度,只需要简单更改L[i]的值即可。
T   T时指向一个数组的指针,在这个数组中存放这select-list或者bind-variable的数据类型。这个成员决定了Oracle数据存储到V数组中时如何进行转换。对于select descriptors,DESCRIBE SELECT LIST语句设置数据类型数组值为Oracle内部数据类型(char ,number或date等)。在进行FETCH前,用户可能需要重新根改此数组某元素的值,因为Oracle内部数据类型很难被C语言所采用。通常为了对select-list对应的select descriptors数据进行显示,需要将数据类型转换成varchar2或STRING类型。T[i]的高位用来指示其对应的select-list列值的“NULL/NOT NULL”状态。在使用OPEN或FETCH语句前,需要调用SQLColumnNullCheck()接受T[i]数据类型值,并清空高位NULL/NOT NULL状态。对于bind descriptors,DESCRIBE BIND VARIABLES设置数据类型数组的各元素值为0。用户必须在OPEN命令前设置各输入宿主变量的数据类型。变量类型值采用Oracle外部数据类型描述。通常,绑定变量值存储在字符串数组中,其对应的T[i]就设置为1(Varchar2)或者5(STRING)。
I   这是一个指向存储指示变量值数组的指针。对于select descriptors,在FETCH语句前必须设置I数组各元素所指向的地址。
    EXEC SQL FETCH ... USING ‘select descriptor’
    如果第i个select-list对应列值为空,则I[i]值为-1 否则是个>=0的整数。
    对于bind descriptors,必须在OPEN语句前设置I数组各变量的值。
    EXEC SQL OPEN ... USING ‘bind descriptor’
F   存放通过DESCRIBE语句得到的select-list或占位符的真实数目,如果经过DESCRIBE语句后F小于零表示DESCRIBE语句发现的select-list数目或占位符数目比分配描述符时指定的最大数据数目N大,例如,如果设置N=10但DESCRIBE发现select-list的数目是11个,那么F将被设置成-11,这允许用户根据此值重新调用

SQLSQLDAAlloc函数分配大的描述符存储区域。
S   指向一个数组的指针,该数组存储了select-list或占位符的名字。
M   指向一个数组的指针,该数组存储了select-list或占位符名字的最大长度。
C   指向一个数组的指针,该数组存储了select-list或占位符名字的当前长度。
X   指向一个存储指示变量名字数组的指针。
Y   指向一个存储指示变量名字最大长度数组的指针。
Z   指向一个存储指示变量名称当前长度数组的指针。

 

未完待续

你可能感兴趣的:(linux,c)