dbms_utility.format_error_backtrace

本文介绍Oracle PL/SQL中DBMS_UTILITY.FORMAT_ERROR_BACKTRACE函数的使用方法,通过实例演示了如何利用此函数来追踪异常发生的堆栈信息,这对于调试和定位错误非常有用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DBMS_UTILITY.FORMAT_ERROR_BACKTRACE

系统为最近一次生成的异常设置了一个栈,并跟踪它的传递过程,而这个函数使用这个栈,然后返回该异常的整个传递过程。这个函数对错误的定位和实施下一步处理起着至关重要的作用。

 

举例:

 

 

CREATE OR REPLACE PROCEDURE proc1 IS
    BEGIN
       DBMS_OUTPUT.put_line ('running proc1');
       RAISE NO_DATA_FOUND;
    END;
    /
 
    CREATE OR REPLACE PROCEDURE proc2 IS
       l_str VARCHAR2 (30) := 'calling proc1';
    BEGIN
       DBMS_OUTPUT.put_line (l_str);
       proc1;
    END;
    /
    CREATE OR REPLACE PROCEDURE proc3 IS
    BEGIN
       DBMS_OUTPUT.put_line ('calling proc2');
       proc2;
    EXCEPTION
       WHEN OTHERS
       THEN
          DBMS_OUTPUT.put_line ('Error stack at top level:');
          DBMS_OUTPUT.put_line (DBMS_UTILITY.format_error_backtrace);
    END;
    /
然后:
    SQL> SET SERVEROUTPUT ON
    SQL> BEGIN
      2     DBMS_OUTPUT.put_line ('Proc3 -> Proc2 -> Proc1 backtrace');
      3     proc3;
      4 END;
      5 /
    Proc3 -> Proc2 -> Proc1 backtrace
    calling proc2
    calling proc1
    running proc1
    Error stack at top level:
    ORA-06512: at "SCOTT.PROC1", line 4
    ORA-06512: at "SCOTT.PROC2", line 5
    ORA-06512: at "SCOTT.PROC3", line 4



每 次异常的产生都将重置这个异常栈,只是最后一次从系统栈出栈的是最外层的程序块,所以可以清楚地看到异常生成的整个过程。上面这个程序的执行过程是:首先用 put_line 打印 Proc3 -> Proc2 -> Proc1 backtrace , 调用 proc3 ,当前程序入栈 => 打印 calling proc2 ,调用 proc2 , proc3 入栈 => 打印 calling proc1 ,调用 proc1 , proc2 入栈 => 打印 running proc1 ,生成 no_data_found 异常,该异常被压入异常栈中 => proc2 出栈,并检测到来自第 5 行调用传递过来的异常,将它在此压入异常栈 => proc3 出栈,并检测到来自第 4 行调用传递过来的异常,将它在此压入异常栈, dbms_utility.format_error_backtrace 将异常栈中信息反相打印出来 => 最外层程序出栈, end 。

使用这个函数的一些注意事项:

1.在当前程序的异常处理模块中调用这个函数。

2.避免在中间程序中使用异常处理模块。

/* Formatted on 2025/7/23 19:23:00 (QP5 v5.326) */ CREATE OR REPLACE PROCEDURE IMES.SP_MES_GET_STATION_INFO_V1 ( T_STATION_NAME IN VARCHAR2, T_LINE OUT VARCHAR2, T_STAGE OUT VARCHAR2, T_STATION_TYPE OUT VARCHAR2, T_MODEL OUT VARCHAR2, TRES OUT VARCHAR2) IS V_TEST_STATION_NAME VARCHAR2 (60); V_COUNT NUMBER; --modify by penn 2021/8/24 PDCA站点根据customer_station_type 转换为station_type --modify by ellis 2024/01/17 增加机种信息 --modify by dulin 2025/02/26 取消通过IMES.M_STATION.STATION_TYPE串 IMES.M_STATION_TYPE.stationtype_customer 逻辑 BEGIN TRES := 'OK'; SELECT A.LINE, A.STAGE, A.STATION_TYPE, B.MODEL INTO T_LINE, T_STAGE, T_STATION_TYPE, T_MODEL FROM IMES.M_STATION A, IMES.M_LINE B WHERE A.LINE = B.LINE AND A.STATION_NAME = T_STATION_NAME AND A.ENABLED = 'Y' AND B.ENABLED = 'Y' AND ROWNUM = 1; EXCEPTION WHEN NO_DATA_FOUND THEN SELECT SUBSTR (T_STATION_NAME, INSTR (T_STATION_NAME, '_', -1, 1) + 1) INTO V_TEST_STATION_NAME FROM DUAL; ---取客户站点 SELECT SUBSTR ( T_STATION_NAME, INSTR (T_STATION_NAME, '_', 1) + 1, INSTR (T_STATION_NAME, '_', INSTR (T_STATION_NAME, '_', 1) + 1) - INSTR (T_STATION_NAME, '_', 1) - 1) INTO T_LINE FROM DUAL; ----取线体 BEGIN SELECT A.STAGE, A.STATION_TYPE INTO T_STAGE, T_STATION_TYPE FROM IMES.M_STATION_TYPE A WHERE A.stationtype_customer = V_TEST_STATION_NAME AND ENABLED = 'Y' --AND STAGE = T_STAGE --抓取到客户站点只有一笔直接抓出,多个站点直接抓空 AND CLIENT_TYPE = 'PDCA' AND ROWNUM = 1; EXCEPTION WHEN OTHERS THEN T_LINE := T_LINE; T_STAGE := ''; T_STATION_TYPE := ''; TRES := IMES.FN_MES_ERROR_CODE_TRANSLATE ('A0002', 'ZH', ''); END; WHEN OTHERS THEN --TRES := SQLERRM || '<' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE || '>'; TRES := IMES.FN_MES_ERROR_CODE_TRANSLATE ( 'B0001', 'ZH', 'SP_MES_GET_STATION_INFO_V1' || SQLERRM || '<' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE || '>'); END; /
07-24
CREATE OR REPLACE PROCEDURE IMES.SP_CHECK_ROUTE ( T_STATIONNAME IN VARCHAR2, T_SN IN VARCHAR2, TRES OUT VARCHAR2) AS V_COUNT NUMBER; V_CURRENT_STATION IMES.P_SN_STATUS.STATION_TYPE%TYPE; --当前站 V_NEXT_STATION IMES.P_SN_STATUS.NEXT_STATION_TYPE%TYPE; --下一站 V_WORK_ORDER IMES.P_SN_STATUS.WORK_ORDER%TYPE; --工单 V_ROUTE_NAME IMES.P_SN_STATUS.ROUTE_NAME%TYPE; --route名字 V_START_STATION IMES.P_SN_STATUS.STATION_TYPE%TYPE; --工单对应开始站 V_CURRENT_STATUS IMES.P_SN_STATUS.CURRENT_STATUS%TYPE; --当前状态 V_SNSTATUS VARCHAR2 (100); --当前状态 V_WORK_FLAG IMES.P_SN_STATUS.WORK_FLAG%TYPE; --SN 是否报废,1报废,0 OK V_INPUT_STATION IMES.P_SN_STATUS.STATION_TYPE%TYPE; --当前站点对应投入站 V_LINE IMES.M_STATION.LINE%TYPE; --线别名字 V_STAGE IMES.M_STATION.STAGE%TYPE; --区段名 V_NEXT_DESC IMES.M_STATION_TYPE.STATION_TYPE_DESC%TYPE; ----下一站描述 BEGIN ---注释页面选择的station对应参数1.0.0.0 By Dulin 2020/12/5 --V1.0.0.1 By Penn 2021/4/21 增加翻译功能 TRES := 'OK'; IMES.SP_GET_PLACE (T_STATIONNAME, v_LINE, v_STAGE, V_INPUT_STATION); ----------------------------------------------------------------SN 当前状态检查--------------------------------------------- BEGIN ------------查询SN当前状态参数----------------- SELECT A.CURRENT_STATUS, IMES.FN_SNStatus_Result (CURRENT_STATUS), A.WORK_FLAG, A.STATION_TYPE, A.ROUTE_NAME, A.NEXT_STATION_TYPE, A.WORK_ORDER INTO V_CURRENT_STATUS, V_SNSTATUS, V_WORK_FLAG, V_CURRENT_STATION, V_ROUTE_NAME, V_NEXT_STATION, V_WORK_ORDER FROM IMES.P_SN_STATUS A WHERE SERIAL_NUMBER = T_SN AND ROWNUM = 1; EXCEPTION WHEN NO_DATA_FOUND THEN --------------SN 不存在------------------------ TRES := IMES.FN_GET_TRANSLATE_MSG ('A0001', --ERR_CODE,PARAM1,PARAM2..PARAM10 T_SN, --INPUT_VALUE V_LINE, --Line T_STATIONNAME, --Station 'SP_CHECK_ROUTE', --PROGRAM '', --IP '', --empNo ''); --Remark GOTO ENDP; WHEN OTHERS THEN TRES := IMES.FN_GET_TRANSLATE_MSG ( 'B0001,SP_CHECK_ROUTE,' || SQLERRM || '<' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE || '>', --ERR_CODE,PARAM1,PARAM2..PARAM10 T_SN, --INPUT_VALUE V_LINE, --Line T_STATIONNAME, --Station 'SP_CHECK_ROUTE', --PROGRAM '', --IP '', --empNo ''); --Remark GOTO ENDP; END; ---------------SN的各种状态------------------ IF V_WORK_FLAG = '1' THEN TRES := 'SCRAP'; ELSIF V_WORK_FLAG = '3' THEN TRES := 'IN LAB'; ELSIF ( V_CURRENT_STATUS = '1' OR V_CURRENT_STATUS = '2' OR V_CURRENT_STATUS = '3' OR V_CURRENT_STATUS = '4' OR V_CURRENT_STATUS = '7') THEN TRES := V_SNSTATUS; ELSE SELECT COUNT (*) INTO V_COUNT FROM IMES.P_QC_OFFLINE A WHERE A.SERIAL_NUMBER = T_SN AND (A.QC_IN_TIME IS NULL OR A.QC_OUT_TIME IS NULL); IF V_COUNT > 0 THEN TRES := ' IN OFFLINE QC!'; END IF; END IF; IF TRES <> 'OK' THEN TRES := IMES.FN_GET_TRANSLATE_MSG ('A0182,SCRAP', --ERR_CODE,PARAM1,PARAM2..PARAM10 T_SN, --INPUT_VALUE '', --Line V_INPUT_STATION, --Station 'SP_CHECK_ROUTE', --PROGRAM '', --IP '', --empNo ''); --Remark GOTO ENDP; END IF; -------------------------SN Hold 检查----------------------------- IMES.SP_CHECK_HOLD (T_SN, T_STATIONNAME, TRES); IF TRES <> 'OK' THEN GOTO ENDP; END IF; -------------------------------------------------------------------------SN 流程检查--------------------------------------------------------------- -----------没有强制指站------------- IF (V_NEXT_STATION IS NULL) OR (V_NEXT_STATION = '0') THEN -----------------SN生成之后未生产过--------------------- IF (V_CURRENT_STATION = '0') THEN BEGIN -----------查询SN对应工单的默认投入站别----------------------- SELECT START_STATION_TYPE INTO V_START_STATION FROM IMES.P_WO_BASE WHERE WORK_ORDER = V_WORK_ORDER AND ROWNUM = 1; EXCEPTION WHEN NO_DATA_FOUND THEN -----------工单不存在--------------------------- TRES := IMES.FN_GET_TRANSLATE_MSG ('A0004', --ERR_CODE,PARAM1,PARAM2..PARAM10 T_SN, --INPUT_VALUE V_LINE, --Line T_STATIONNAME, --Station 'SP_CHECK_ROUTE', --PROGRAM '', --IP '', --empNo ''); --Remark GOTO ENDP; WHEN OTHERS THEN TRES := IMES.FN_GET_TRANSLATE_MSG ( 'B0001,SP_CHECK_ROUTE,' || SQLERRM || '<' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE || '>', --ERR_CODE,PARAM1,PARAM2..PARAM10 T_SN, --INPUT_VALUE V_LINE, --Line T_STATIONNAME, --Station 'SP_CHECK_ROUTE', --PROGRAM '', --IP '', --empNo ''); --Remark GOTO ENDP; END; --如果工单对应站别等于当前所选站点对应的投入站别 IF (V_START_STATION = V_INPUT_STATION) THEN TRES := 'OK'; ELSE SELECT IMES.FN_GET_STATIONTYPE_DESC (V_START_STATION) INTO V_NEXT_DESC FROM DUAL; ------工单开始站不存在--------- IF V_NEXT_DESC = '' OR V_NEXT_DESC IS NULL THEN --TRES := 'WO Start Station Type NG'; TRES := IMES.FN_GET_TRANSLATE_MSG ('A0583', --ERR_CODE,PARAM1,PARAM2..PARAM10 T_SN, --INPUT_VALUE V_LINE, --Line T_STATIONNAME, --Station 'SP_CHECK_ROUTE', --PROGRAM '', --IP '', --empNo ''); --Remark ELSE --------------------------工单开始站点存在,报错SN 流程错误------------------- TRES := IMES.FN_GET_TRANSLATE_MSG ( 'A0416,' || T_SN || ',' || V_START_STATION || '(' || V_NEXT_DESC || ')', --ERR_CODE,PARAM1,PARAM2..PARAM10 T_SN, --INPUT_VALUE V_LINE, --Line T_STATIONNAME, --Station 'SP_CHECK_ROUTE', --PROGRAM '', --IP '', --empNo ''); --Remark END IF; END IF; ELSE ---------如果SN当前站点不为空,正常流程检查----------------- BEGIN --------------------根据当前站点及SN状态和下一站查询流程,能够查到说明流程正确-------------------------- SELECT NEXT_STATION_TYPE INTO V_NEXT_STATION FROM IMES.M_ROUTE_DETAIL WHERE RESULT = V_CURRENT_STATUS AND ROUTE_NAME = V_ROUTE_NAME AND STATION_TYPE = V_CURRENT_STATION AND NEXT_STATION_TYPE = V_INPUT_STATION AND ROWNUM = 1; TRES := 'OK'; EXCEPTION WHEN OTHERS THEN BEGIN --------------------流程错误,获取下一站站点名称并报错--------------------------- SELECT NEXT_STATION_TYPE INTO V_NEXT_STATION FROM IMES.M_ROUTE_DETAIL A WHERE A.ROUTE_NAME = V_ROUTE_NAME AND A.SEQ = (SELECT MAX (SEQ) FROM IMES.M_ROUTE_DETAIL WHERE STATION_TYPE = V_CURRENT_STATION AND ROUTE_NAME = V_ROUTE_NAME AND RESULT = V_CURRENT_STATUS); TRES := IMES.FN_GET_TRANSLATE_MSG ( 'A0416,' || T_SN || ',' || V_NEXT_STATION || '(' || IMES.FN_GET_STATIONTYPE_DESC ( V_NEXT_STATION) || ')', --ERR_CODE,PARAM1,PARAM2..PARAM10 T_SN, --INPUT_VALUE V_LINE, --Line T_STATIONNAME, --Station 'SP_CHECK_ROUTE', --PROGRAM '', --IP '', --empNo ''); --Remark EXCEPTION WHEN OTHERS THEN ---------------根据当前站在流程里面查不到下一站,如果是良品状态则ROUTE END,否则REPAIR NG---------- IF V_CURRENT_STATUS = '0' THEN TRES := 'ROUTE END'; ELSE TRES := 'REPAIR NG'; END IF; END; END; END IF; ELSE ----------------------------------有强制指站------------------------------- IF ((V_CURRENT_STATUS = '0') OR (V_CURRENT_STATUS = '9')) THEN IF V_NEXT_STATION = V_INPUT_STATION THEN TRES := 'OK'; ELSE TRES := IMES.FN_GET_TRANSLATE_MSG ( 'A0416,' || T_SN || ',' || V_NEXT_STATION || '(' || IMES.FN_GET_STATIONTYPE_DESC (V_NEXT_STATION) || ')', --ERR_CODE,PARAM1,PARAM2..PARAM10 T_SN, --INPUT_VALUE V_LINE, --Line T_STATIONNAME, --Station 'SP_CHECK_ROUTE', --PROGRAM '', --IP '', --empNo ''); --Remark END IF; ELSE TRES := 'REPAIR NG'; END IF; END IF; <<ENDP>> NULL; EXCEPTION WHEN OTHERS THEN TRES := IMES.FN_GET_TRANSLATE_MSG ( 'B0001,SP_CHECK_ROUTE,' || SQLERRM || '<' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE || '>', --ERR_CODE,PARAM1,PARAM2..PARAM10 T_SN, --INPUT_VALUE V_LINE, --Line T_STATIONNAME, --Station 'SP_CHECK_ROUTE', --PROGRAM '', --IP '', --empNo ''); END; /
最新发布
07-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值