OCI编程基础篇(五) 处理错误信息
访问www.tomcoding.com网站,学习Oracle内部数据结构,详细文档说明,下载Oracle的exp/imp,DUL,logminer,ASM工具的源代码,学习高技术含量的内容。
前面我们看到了连接数据库的过程,调用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);
这样看起来是不是简洁多了。

浙公网安备 33010602011771号