处理 python 和 oracle 之间异常握手的正确方法
Correct way to handle exception handshake between python and oracle
我正在从 Python 调用以下过程,问题是我无法看到块中出现的异常,现在为了重现我已经强制引发异常但我无法在 Python 副脚本
中看到这一点
CREATE OR REPLACE FUNCTION mark_step
(
batch_id IN NUMBER
,request_id IN VARCHAR2
) RETURN NUMBER IS
BEGIN
INSERT INTO temp_log VALUES ('entered');
RAISE no_data_found;
return 0;
EXCEPTION
WHEN OTHERS THEN
INSERT INTO temp_log VALUES ('exception');
END mark_step;
调用此函数的客户端脚本
l_result = cur.callfunc('mark_step', cx_Oracle.STRING,
[batch_id,request_id])
print(l_result)
该函数优雅地处理了异常,并且Python脚本没有获得在异常块上添加 Raise 失败的函数的任何可见性
EXCEPTION
WHEN OTHERS THEN
INSERT INTO temp_log VALUES ('exception');
RAISE;
END mark_step;
在 Python 方面,您可以添加 try , except 块以明确处理异常,以防您尚未这样做
try:
l_result = cur.callfunc('credit_ref_mig.mark_step', cx_Oracle.STRING,
[batch_id,request_id])
print(l_result)
except as e:
print(e)
我认为没有问题,除了在您的代码中 exception block
中缺少 return value
。
您的 function
引发的 exception
由 function
本身包含的 exception block
处理。
演示如下:
正在创建 table
SQL> CREATE TABLE TEMP_LOG (
2 LOG_ VARCHAR2(50)
3 );
Table created.
SQL>
正在创建 function
,请参阅内嵌注释:
SQL> CREATE OR REPLACE FUNCTION MARK_STEP (
2 BATCH_ID IN NUMBER,
3 REQUEST_ID IN VARCHAR2
4 ) RETURN NUMBER IS
5 BEGIN
6 INSERT INTO TEMP_LOG VALUES ( 'entered' );
7 RAISE NO_DATA_FOUND; -- error raised by this statement will be handeled by following exception block
8 RETURN 0;
9 EXCEPTION
10 WHEN OTHERS THEN
11 INSERT INTO TEMP_LOG VALUES ( 'exception' );
12 RETURN -1; -- this is misssing in your code
13 END;
14 /
Function created.
SQL>
调用函数:
SQL> SET SERVEROUT ON
SQL>
SQL> DECLARE
2 CNT NUMBER;
3 BEGIN
4 CNT := MARK_STEP(1, 'v');
5 DBMS_OUTPUT.PUT_LINE('result := ' || CNT);
6 COMMIT;
7 END;
8 /
result := -1
PL/SQL procedure successfully completed.
SQL>
检查temp_log中的数据 table:
SQL> SELECT * FROM TEMP_LOG;
LOG_
--------------------------------------------------
entered
exception
SQL>
看到两个部分都已执行,function
的结果也是 -1
。
现在,如果您想将错误报告给外部调用程序,那么您可以删除整个 exception block
,如下所示:
SQL> CREATE OR REPLACE FUNCTION MARK_STEP (
2 BATCH_ID IN NUMBER,
3 REQUEST_ID IN VARCHAR2
4 ) RETURN NUMBER IS
5 BEGIN
6 INSERT INTO TEMP_LOG VALUES ( 'entered' );
7
8 COMMIT; -- added commit to see if it is working or not
9 RAISE NO_DATA_FOUND; -- error raised by this statement will be handeled by following exception block
10 RETURN 0;
11 --EXCEPTION
12 -- WHEN OTHERS THEN
13 -- INSERT INTO TEMP_LOG VALUES ( 'exception' );
14 -- RETURN -1; -- this is misssing in your code
15 END;
16 /
Function created.
SQL>
调用更新后的 function
并检查 temp_log
table 中的数据。
SQL> TRUNCATE TABLE TEMP_LOG;
Table truncated.
SQL> SET SERVEROUT ON
SQL>
SQL> DECLARE
2 CNT NUMBER;
3 BEGIN
4 CNT := MARK_STEP(1, 'v');
5 DBMS_OUTPUT.PUT_LINE('result := ' || CNT);
6 COMMIT;
7 END;
8 /
DECLARE
*
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at "TEJASH.MARK_STEP", line 9
ORA-06512: at line 4
SQL> SELECT * FROM TEMP_LOG;
LOG_
--------------------------------------------------
entered
SQL>
看,现在抛出了 error
,raise exception
上面的所有代码都按预期工作了。
我希望,你觉得这很有用。
干杯!!
我正在从 Python 调用以下过程,问题是我无法看到块中出现的异常,现在为了重现我已经强制引发异常但我无法在 Python 副脚本
中看到这一点CREATE OR REPLACE FUNCTION mark_step
(
batch_id IN NUMBER
,request_id IN VARCHAR2
) RETURN NUMBER IS
BEGIN
INSERT INTO temp_log VALUES ('entered');
RAISE no_data_found;
return 0;
EXCEPTION
WHEN OTHERS THEN
INSERT INTO temp_log VALUES ('exception');
END mark_step;
调用此函数的客户端脚本
l_result = cur.callfunc('mark_step', cx_Oracle.STRING,
[batch_id,request_id])
print(l_result)
该函数优雅地处理了异常,并且Python脚本没有获得在异常块上添加 Raise 失败的函数的任何可见性
EXCEPTION
WHEN OTHERS THEN
INSERT INTO temp_log VALUES ('exception');
RAISE;
END mark_step;
在 Python 方面,您可以添加 try , except 块以明确处理异常,以防您尚未这样做
try:
l_result = cur.callfunc('credit_ref_mig.mark_step', cx_Oracle.STRING,
[batch_id,request_id])
print(l_result)
except as e:
print(e)
我认为没有问题,除了在您的代码中 exception block
中缺少 return value
。
您的 function
引发的 exception
由 function
本身包含的 exception block
处理。
演示如下:
正在创建 table
SQL> CREATE TABLE TEMP_LOG ( 2 LOG_ VARCHAR2(50) 3 ); Table created. SQL>
正在创建 function
,请参阅内嵌注释:
SQL> CREATE OR REPLACE FUNCTION MARK_STEP ( 2 BATCH_ID IN NUMBER, 3 REQUEST_ID IN VARCHAR2 4 ) RETURN NUMBER IS 5 BEGIN 6 INSERT INTO TEMP_LOG VALUES ( 'entered' ); 7 RAISE NO_DATA_FOUND; -- error raised by this statement will be handeled by following exception block 8 RETURN 0; 9 EXCEPTION 10 WHEN OTHERS THEN 11 INSERT INTO TEMP_LOG VALUES ( 'exception' ); 12 RETURN -1; -- this is misssing in your code 13 END; 14 / Function created. SQL>
调用函数:
SQL> SET SERVEROUT ON SQL> SQL> DECLARE 2 CNT NUMBER; 3 BEGIN 4 CNT := MARK_STEP(1, 'v'); 5 DBMS_OUTPUT.PUT_LINE('result := ' || CNT); 6 COMMIT; 7 END; 8 / result := -1 PL/SQL procedure successfully completed. SQL>
检查temp_log中的数据 table:
SQL> SELECT * FROM TEMP_LOG; LOG_ -------------------------------------------------- entered exception SQL>
看到两个部分都已执行,function
的结果也是 -1
。
现在,如果您想将错误报告给外部调用程序,那么您可以删除整个 exception block
,如下所示:
SQL> CREATE OR REPLACE FUNCTION MARK_STEP ( 2 BATCH_ID IN NUMBER, 3 REQUEST_ID IN VARCHAR2 4 ) RETURN NUMBER IS 5 BEGIN 6 INSERT INTO TEMP_LOG VALUES ( 'entered' ); 7 8 COMMIT; -- added commit to see if it is working or not 9 RAISE NO_DATA_FOUND; -- error raised by this statement will be handeled by following exception block 10 RETURN 0; 11 --EXCEPTION 12 -- WHEN OTHERS THEN 13 -- INSERT INTO TEMP_LOG VALUES ( 'exception' ); 14 -- RETURN -1; -- this is misssing in your code 15 END; 16 / Function created. SQL>
调用更新后的 function
并检查 temp_log
table 中的数据。
SQL> TRUNCATE TABLE TEMP_LOG; Table truncated. SQL> SET SERVEROUT ON SQL> SQL> DECLARE 2 CNT NUMBER; 3 BEGIN 4 CNT := MARK_STEP(1, 'v'); 5 DBMS_OUTPUT.PUT_LINE('result := ' || CNT); 6 COMMIT; 7 END; 8 / DECLARE * ERROR at line 1: ORA-01403: no data found ORA-06512: at "TEJASH.MARK_STEP", line 9 ORA-06512: at line 4 SQL> SELECT * FROM TEMP_LOG; LOG_ -------------------------------------------------- entered SQL>
看,现在抛出了 error
,raise exception
上面的所有代码都按预期工作了。
我希望,你觉得这很有用。
干杯!!