You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 18:23:13