存储过程异常处理

Posted

技术标签:

【中文标题】存储过程异常处理【英文标题】:Stored procedure exception handling 【发布时间】:2011-09-29 11:47:18 【问题描述】:
SQL>  DECLARE
2    TotalUpd   NUMBER(36) := 0;
3  BEGIN
4   dbms_output.put_line ('Job Start time............... : ' || to_char(SYSDATE, '             hh24:mi:ss'));
5   UPDATE Asset SET _status = 'PROGRESS' WHERE status is null;
6   TotalUpd := SQL%ROWCOUNT;
7   dbms_output.put_line('Total Records Updated. : ' || TotalUpd);
8    COMMIT;
9   EXCEPTION
10   WHEN NO_DATA_FOUND THEN
11  dbms_output.put_line ('No more data to update.');
12  WHEN OTHERS THEN
13  dbms_output.put_line ('Error while status as SUCCESS ');
14  END ;
15  /

上述过程的结果是 作业开始时间...... : 04:41:41 更新的总记录。 : 0

但是我的预期结果是“没有更多的行要更新”必须打印,因为我已经截断了表 Asset。请告诉我哪里出错了。

【问题讨论】:

【参考方案1】:

NO_DATA_FOUND 错误不会在更新语句中引发。

如果 select 语句不返回任何内容,则会在 select into 语句中抛出。

另请参阅 select_item 下的 Tahiti on select into:*如果 SELECT INTO 语句不返回任何行,PL/SQL 将引发预定义的异常 NO_DATA_FOUND。*

如果更新语句没有更新任何内容,Oracle 不会将其视为异常,因此不会引发异常。然而,如果一个 select into 语句不能填充变量,它被认为是一个错误(因此在这种情况下 NO_DATA_EXCEPTION 被抛出(

【讨论】:

【参考方案2】:

很简单,如果没有数据,更新不会产生错误。

如果你想控制你的代码流,你需要查看TotalUpd的值

 DECLARE 
 TotalUpd   NUMBER(36) := 0;
 BEGIN
    dbms_output.put_line ('Job Start time............... : ' 
        || TO_CHAR(SYSDATE, '             hh24:mi:ss'));
    UPDATE Asset SET _status = 'PROGRESS' WHERE status IS null;
    TotalUpd := SQL%ROWCOUNT; 
    IF TotalUpd = 0 THEN
        dbms_output.put_line ('No more data to update.');
    ELSE
        dbms_output.put_line('Total Records Updated. : '
            || TotalUpd);
    END IF; 
    COMMIT; 
 EXCEPTION 
 WHEN OTHERS THEN
    dbms_output.put_line ('Error while status as SUCCESS '); 
 END; 

【讨论】:

您可以在使用 WHEN OTHERS 异常时添加 SQLERRM 和 SQLCODE。 WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('ERROR IS : ' || SQLCODE || ' : ' || SQLERRM); @Mahi007 - SQLERRM 已经包含 SQLCODE。并且通常不建议使用调试消息处理 OTHERS 异常。 请记住,我只是在回答所提出的问题,我发现最好假设功能是正确的,并且可能对输出存在依赖性。 @William Robertson - 同意 Sqlerrm 包含 sqlcode。我认为它是非生产环境。也许使用“找不到数据时”然后引发应用程序错误(-20001,)似乎是更好的选择,或者插入到错误日志表中【参考方案3】:

如果select into 不返回任何行,则抛出NO_DATA_FOUND,而不是如果在更新语句后没有更新任何行。

我建议您在更新本身之后移动处理此异常的逻辑:

IF (SQL%ROWCOUNT = 0) THEN  
  dbms_output.put_line ('No more data to update.');

【讨论】:

【参考方案4】:

认为 NO_DATA_FOUND 异常仅由您未使用的 SELECT 语句引发。尝试测试 SQL%COUNT 并根据需要输出。

【讨论】:

...我猜你是想写SQL%ROWCOUNT

以上是关于存储过程异常处理的主要内容,如果未能解决你的问题,请参考以下文章

Oracle存储过程的异常处理

Informix 存储过程通用异常处理

oracle 存储过程异常处理

Mysql存储过程——异常处理

存储过程异常处理

PostgreSQL存储过程-异常错误处理