OCI编程基础篇(五) 处理错误信息

前面我们看到了连接数据库的过程,调用OCI函数的过程中可能出现错误,那么怎样得到出错的信息呢?我们平时看到的ORA-XXXXX等错误都有详细的信息,好让我们来诊断错误的原因,下面就来看看怎样处理这些错误。

我们在创建完OCI环境句柄后,第一个分配的句柄就是错误句柄,以后的每个OCI函数调用时都会把这个句柄传给函数,在函数执行过程中如果遇到错误,就会把错误码和错误信息与这个句柄关联起来,调用返回错误后,就可以利用这个句柄得到特定的错误码和详细的错误信息。

通过错误句柄得到错误信息需要一个函数,叫做OCIErrorGet(),函数原型和参数如下。

sword OCIErrorGet ( void *hndlp,
    ub4        recordno,
    OraText *sqlstate,
    sb4        *errcodep,
    OraText *bufp,
    ub4        bufsiz,
    ub4        type );

hndlp是一个输入参数,指定从哪个句柄提取错误信息,一般都是错误句柄,有些函数没有传入错误句柄的,比如OCIHandleAlloc(),只传入了环境句柄,那么这儿的参数就是环境句柄。

recordno是一个输入参数,指定错误记录号,也就是提取哪个错误的信息,一般赋值为1,提取第一个错误。

sqlstate是一个输出参数,这个参数已经作废了。

errcodep是一个输出参数,返回一个错误码,就是ORA-XXXXX后面的XXXXX。

bufp是一个输出参数,返回出错的消息文本。

bufsiz是一个输入参数,指示存放出错消息的缓冲区bufp的大小。如果太小的缓冲区,错误消息文本会被截断,而且还会报错。

type是一个输入参数,指示传入的句柄是错误句柄还是环境句柄,一般为错误句柄。

举一个例子,比如前面连接数据库时,建立服务器句柄与数据库的通信路径出现错误,用下面的代码取得错误信息。

/* 定义错误码和错误信息 */

int       ec;

char    errbuf[512];


rc = OCIServerAttach(
        svrhp,
        errhp,
        (CONST text *)NULL,
        0,
        OCI_DEFAULT
);

if (rc != OCI_SUCCESS) {
        OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
        fprintf(stderr, "OCIServerAttach() - [%d] %s\n", ec, errbuf);
        return (-1);
}
下面我们写一个函数来处理OCI函数的返回值,这样就不用每次都处理错误了,在这个函数中一次处理完毕。

/* 定义两个全局变量,一个返回错误码,一个返回错误信息文本 */
int	    oci_errcode;
char	oci_errmsg[16384];

int check_oci_error(OCIError *errhp, sword status)
{
    sb4		ec;

    oci_errcode = 0;
    switch (status) {
        /* 调用函数成功 */
        case OCI_SUCCESS:
        /* 需要提供进一步的数据,留待调用逻辑处理 */
        case OCI_NEED_DATA:
        /* 查询后没有数据返回,留待调用逻辑处理 */
        case OCI_NO_DATA:
            return (status);

        case OCI_ERROR:
            if (OCIErrorGet((void *)errhp, (ub4)1, (OraText *)NULL, &ec,
                (OraText *)oci_errmsg, 16383, OCI_HTYPE_ERROR) != OCI_SUCCESS) {
                oci_errcode = -1;
                fprintf(stderr, "need bigger buffer for error message.\n");
                return (-1);
            }

            oci_errcode = ec;
            oci_errmsg[16383] = '\0';
            fprintf(stderr, "Error - [%d] %s\n", oci_errcode, oci_errmsg);
            return (status);

        case OCI_SUCCESS_WITH_INFO:
            if (OCIErrorGet((void *)errhp, (ub4)1, (OraText *)NULL, &ec,
                (OraText *)oci_errmsg, 16383, OCI_HTYPE_ERROR) != OCI_SUCCESS) {
                oci_errcode = -1;
                fprintf(stderr, "need bigger buffer for error message.\n");
                return (-1);
            }

            oci_errcode = ec;
            oci_errmsg[16383] = '\0';
            fprintf(stderr, "Warning - [%d] %s\n", oci_errcode, oci_errmsg);
            return (status);

        case OCI_INVALID_HANDLE:
            oci_errcode = -1;
            sprintf(oci_errmsg, "Error - OCI_INVALID_HANDLE");
            fprintf(stderr, "Error - OCI_INVALID_HANDLE\n");
            break;

        case OCI_STILL_EXECUTING:
            oci_errcode = -1;
            sprintf(oci_errmsg, "Error - OCI_STILL_EXECUTING");
            fprintf(stderr, "Error - OCI_STILL_EXECUTING\n");
            break;

        case OCI_CONTINUE:
            oci_errcode = -1;
            sprintf(oci_errmsg, "Error - OCI_CONTINUE");
            fprintf(stderr, "Error - OCI_CONTINUE\n");
            break;

        default:
            oci_errcode = -1;
            sprintf(oci_errmsg, "Error - [%d] Unknow OCI error", status);
            fprintf(stderr, "Error - [%d] Unknow OCI error\n", status);
    }


    return (-1);
}

使用上面的函数我们改写一下连接数据库中,建立服务器句柄与数据库通信路径出错的情况。

if (check_oci_error(errhp, OCIServerAttach(
        svrhp,
        errhp,
        (CONST text *)NULL,
        0,
        OCI_DEFAULT
)) < 0)  return (-1);

这样看起来是不是简洁多了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值