Python-oracledb调用PL/SQL时如何获取自定义异常的错误码与信息?
如何在Python的oracledb中获取PL/SQL存储过程的自定义异常代码和信息
你的问题核心在于两点:一是PL/SQL里的自定义异常未绑定特定错误码,Oracle默认给这类异常分配SQLCODE=1、错误信息为"User-Defined Exception";二是存储过程抛出异常后,Python的oracledb优先捕获这个默认异常,导致你无法正确拿到存储过程中OUT参数的自定义值。
下面提供两种可行的解决办法:
办法一:给PL/SQL自定义异常绑定错误码
在PL/SQL包中使用PRAGMA EXCEPTION_INIT将自定义异常与目标错误码绑定,这样抛出异常时Oracle会直接返回对应错误码和信息,Python端可直接捕获:
修改后的PL/SQL代码:
-- 将自定义异常绑定到错误码-20001 PROCESSING_ERROR EXCEPTION; PRAGMA EXCEPTION_INIT(PROCESSING_ERROR, -20001); PROCEDURE my_procedure( exception_code OUT NUMBER, exception_message OUT VARCHAR2) IS row_count number; BEGIN -- 初始化返回参数 exception_code := 0; exception_message := NULL; select count(*) from my_table into row_count; if row_count > 0 then -- 直接抛出带自定义信息的指定错误码异常 raise_application_error(-20001, 'Data violated business logic'); end if; EXCEPTION WHEN PROCESSING_ERROR THEN dbms_output.put_line('Business rule or schema rule errors.'); exception_code := SQLCODE; exception_message := SQLERRM; -- 重新抛出异常,让Python端捕获 RAISE; WHEN OTHERS THEN exception_code := SQLCODE; exception_message := 'my_procedure: ' || SUBSTR(SQLERRM, 1, 255); RAISE; END my_procedure;
对应的Python代码可直接从异常对象提取信息:
import oracledb try: cursor.callproc('my_package.my_procedure', []) except oracledb.Error as e: err, = e.args print(f"({err.code}, '{err.message}')")
执行后即可得到预期的(-20001, 'Data violated business logic')。
办法二:用OUT参数返回错误,阻止存储过程抛出异常
如果不想让存储过程抛出异常,而是通过OUT参数传递错误信息,只需在PL/SQL的EXCEPTION块处理完成后用RETURN结束存储过程,不传播异常:
修改PL/SQL的EXCEPTION块部分:
EXCEPTION WHEN PROCESSING_ERROR THEN dbms_output.put_line('Business rule or schema rule errors.'); exception_code := -20001; exception_message := 'Data violated business logic'; -- 结束存储过程,不抛出异常 RETURN; WHEN OTHERS THEN exception_code := SQLCODE; exception_message := 'my_procedure: ' || SUBSTR(SQLERRM, 1, 255); RETURN;
对应的Python代码无需捕获异常,直接读取OUT参数的值:
import oracledb exception_code = cursor.var(int) exception_message = cursor.var(str) # 存储过程已处理异常,不会触发except块 cursor.callproc('my_package.my_procedure', [exception_code, exception_message]) # 获取OUT参数的实际值 print(f"({exception_code.getvalue()}, '{exception_message.getvalue()}')")
这样也能得到你想要的输出结果。
内容的提问来源于stack exchange,提问作者acdn
相关产品推荐
相关产品推荐

