OCIErrorGet 和OCI_ERROR的多个错误处理
OCIErrorGet and multiple error handling for OCI_ERROR
对于OCIErrorGet()
,据记载,它可能会返回多个错误,我使用以下方法提取这些错误以进行OCI_SUCCESS_WITH_INFO
,但目前不适用于OCI_ERROR
:
void check_error( sword status )
{
switch( status ) {
case OCI_SUCCESS:
break;
case OCI_SUCCESS_WITH_INFO:
{
ub4 recordno = 1;
while( status != OCI_NO_DATA ) {
sb4 errcode = 0;
text errbuf[ 1024 ];
status = ::OCIErrorGet( m_err, recordno, (text*)NULL, &errcode, errbuf, sizeof( errbuf ), OCI_HTYPE_ERROR );
if( status == OCI_SUCCESS ) {
std::cout << "oracle info: " << (const char*)errbuf << std::endl;
}
else {
assert( status == OCI_NO_DATA );
}
++recordno;
}
}
break;
case OCI_ERROR:
{
sb4 errcode = 0;
text errbuf[ 1024 ];
// note here: no check of returned value from OCIErrorCode(), no loop!
::OCIErrorGet( m_err, 1, (text*)NULL, &errcode, errbuf, sizeof( errbuf ), OCI_HTYPE_ERROR );
throw my_oracle_error( errcode, (const char*)errbuf );
}
break;
default:
throw "something else";
}
}
(当然真正的代码有点不同,但重要的部分如上所示)。
如果是OCI_ERROR
(在上面的代码中标有注释),我的问题是:
- 我是否需要类似的循环,或者 Oracle 是否保证/记录在这种情况下只能返回一个错误?
- 在这种情况下,我需要检查
OCIErrorGet()
返回的值吗? - 如果可以返回多个错误,我应该使用哪个
errcode
来处理引发的异常?
答案最好链接到 Oracle 的文档。
Oracle 保证每次调用OCIErrorGet()
只返回一个错误(注意单数):
在提供的缓冲区中返回错误消息和 Oracle 数据库错误代码。
...
可以通过重复调用 OCIErrorGet() 来检索多个诊断记录,直到没有更多记录(返回OCI_NO_DATA)。OCIErrorGet() 最多返回一条诊断记录。
是否需要类似的循环,也取决于您调用的 (PL/)SQL 代码。简单的 SQL 语句一般只会返回一个错误代码;例如:
SQL> select 1/0 from dual;
select 1/0 from dual
*
ERROR at line 1:
ORA-01476: divisor is equal to zero
但是,如果涉及PL/SQL可能会返回更多:
SQL> begin
2 raise_application_error(-20000, 'error');
3 end;
4 /
begin
*
ERROR at line 1:
ORA-20000: error
ORA-06512: at line 2
在这里,您感兴趣的实际错误是ORA-20000。Oracle 的异常传播从内部块到外部块,因此,假设您没有处理编译错误,则错误的原始原因将是第一个异常。如果您确实捕获并重新引发异常,则会更改。Oracle 在文档中给出的示例是:
SQL> begin
2 dbms_output.put_line(1/0); -- handled
3 exception when zero_divide then
4 dbms_output.put_line(1/0 || ' is undefined'); -- not handled
5 end;
6 /
begin
*
ERROR at line 1:
ORA-01476: divisor is equal to zero
ORA-06512: at line 4
ORA-01476: divisor is equal to zero
DBMS_OUTPUT.PUT_LINE
是一个过程,因此相同的异常出现两次;请注意,它仍然是您感兴趣的第一个异常。
要回答您的问题:
你不需要类似的循环;如果你想得到多个错误代码,你只应该使用一个。
如果返回多个错误,您可能应该抛出第一个错误代码,因为 Oracle 传播异常的方法;这本质上是您需要做出的判断调用。从文档中不清楚OCIErrorGet()
是首先返回最新还是最早的异常;您可能需要引发最后一个异常。
我解决了这个问题:
std::string checkOciErr( OCIError* errhp, sword status ){
std::stringstream ss;
text errbuf[10240];
sb4 errcode;
bool ret_code = true;//
switch (status) {
case OCI_SUCCESS:
ret_code = false;
break;
case OCI_SUCCESS_WITH_INFO:
OCIErrorGet ((dvoid *) errhp, (ub4) 1, (text *) NULL, &errcode, errbuf, (ub4) sizeof(errbuf), (ub4) OCI_HTYPE_ERROR);
ss << " Error: OCI_SUCCESS_WITH_INFO; Info: " << errbuf << endl;
ret_code = (errcode == 436 || errcode == 437 || errcode == 438 || errcode == 439);
break;
case OCI_NEED_DATA:
ss << " Error: OCI_NEED_DATA"<< endl;
break;
case OCI_NO_DATA:
ss << " Error: OCI_NO_DATA"<< endl;
break;
case OCI_ERROR:{
int rc_l = 0;
int recordno = 1;
ss << " Error: ";
while ( rc_l !=OCI_NO_DATA){
text errbuf1[10240];
rc_l = OCIErrorGet ((dvoid *) errhp, (ub4) recordno, (text *) NULL, &errcode, errbuf1, (ub4) sizeof(errbuf1), (ub4) OCI_HTYPE_ERROR);
ss << errbuf1 << endl;
recordno++;
}
}
break;
case OCI_INVALID_HANDLE:
ss << " Error: OCI_INVALID_HANDLE" << endl;
break;
case OCI_STILL_EXECUTING:
ss << " Error: OCI_STILL_EXECUTE"<< endl;
break;
case OCI_CONTINUE:
ss << " Error: OCI_CONTINUE" << endl;
break;
default:
ss << " Error: UNKNOWN(" << status << ")" << endl;
break;
}
return ss.str();
}
输出:
Error: ORA-20000: My Raise!!!
ORA-06512: at "OWNER.RAISEERROR", line 7
ORA-06512: at "OWNER.MYPACKAGE", line 214
ORA-06512: at line 1
- 错误处理.将系统错误代码映射到泛型
- 通过错误处理,在C++中可靠地获得用户十六进制输入
- posix_spawn():使用posix_scawn()时的错误处理问题
- 在C++中样板"冷/never_inline"错误处理技术的最佳方法是什么?
- 关于 istream 中的错误处理的问题
- 程序使用的 C 库中的错误处理C++
- C++ 错误检查 fstream open() 命令和一般字符串流错误处理
- 使用std::tie进行类似golang的错误处理,同时返回结果,是否有缺点?(C++11)
- Boost进程"系统"功能中的错误处理
- RPN计算器c++错误处理和多个运算符
- 提升精神 x3 错误处理程序与期望
- 构造函数中的错误处理而不会失败
- 当 C++ 中函数参数的输入类型(类)错误时的错误处理
- 关于 ocilib 错误处理的问题,如何使用 ocilib 正确捕获日志错误?
- 我可以使用 std::optional 进行错误处理吗?
- C++ main() 末尾关于错误处理的错误
- 抽象包装带有异常的 C 错误处理的最佳方法
- vwprintf错误处理(ERRNO显示0)
- C++ 使用枚举进行错误处理
- 在 C++ 中创建自己的错误处理机制