无法在oracle中调用异常块

时间:2017-07-12 10:39:21

标签: oracle exception exception-handling oracle-sqldeveloper

我试图在我的oracle开发人员版本中执行下面的pl sql块。我调用了函数和过程并且它可以运行罚款。但是如果我的查询没有被执行,我无法调用异常。我有一直试图通过传递一个字符串值而不是int值来得到一个错误的查询。所以它抛出错误但我还需要在出现这种错误时才能执行异常块。块2应该通过异常,因为我传递字符串值。但是异常块没有得到调用,任何帮助?以下是我的块

DECLARE  
  DBCID INT := 102;
  CNT INT;  
BEGIN  
  SELECT DEVOPS_ISDBCEXECUTED(DBCID, 'DDL') INTO CNT FROM DUAL;  
  IF (CNT = 0) THEN  
    BEGIN  
      DEVOPS_DBCINSERT (DBCID,'DDL','hsolanki','Prj1','Item1','avarne');
          BEGIN
            DECLARE W_CNT int;
            BEGIN
            SELECT COUNT(*) INTO W_CNT FROM HS WHERE NAM = 'DK';   //block 1
                IF (W_CNT = 0) THEN 
                INSERT INTO HS
                  (NAM, AGE)
              VALUES    ('Dk',8);
                END IF;
            END;
          END;


          BEGIN
            DECLARE W_CNT int;
            BEGIN
            SELECT COUNT(*) INTO W_CNT FROM HS WHERE NAM = 'Ab';
                IF (W_CNT = 0) THEN 
                INSERT INTO HS
                  (NAM, AGE)                     //block 2
              VALUES    ('Ab',s);
                END IF;
            END;
          END;
       DEVOPS_DBCUPDATE(DBCID, NULL,'SUCCESS');  
    EXCEPTION
      WHEN OTHERS THEN 
        DBMS_OUTPUT.PUT_LINE ('ERROR OCCURED : ' || sqlerrm); 
         DEVOPS_DBCUPDATE (DBCID,sqlerrm,'Failed');     
         rollback;
     END;           
  END IF;  
END;

3 个答案:

答案 0 :(得分:1)

您的异常处理块在' IF(CNT = 0)THEN .. END IF'块。如果传递一个字符串值,很可能是在第一个函数调用(SELECT DEVOPS_ISDBCEXECUTED ...)中抛出了异常,该调用未被保护'由一个excpetion处理程序。您需要将异常处理程序移动到最外面的块,例如:

DECLARE  
  DBCID INT := 102;
  CNT INT;  
BEGIN  
....
EXCEPTION
      WHEN OTHERS THEN 
    ...
END;

答案 1 :(得分:1)

所以我们知道......

  

DEVOPS_DBCUPDATE是更新表

的过程

......和......

  

异常我正在调用DEVOPS_DBCUPDATE ...我的表没有得到更新

......和......

  

我不知道什么是pragma autonomous_transaction

完全提出这些线索,我们可以看到EXCEPTION块中的rollback将消除前一次调用DEVOPS_DBCUPDATE()所执行的表的更改,所以只有似乎好像没有执行EXCEPTION块(检查是否显示DBMS_OUTPUT消息会确认它正在被调用)。

无论如何,解决方案是使DEVOPS_DBCUPDATE()在嵌套事务中运行,因此无论更广泛的事务中发生什么,都会应用更改。我们使用autonomous_transaction pragma执行此操作。

显然我不知道代码的确切结构,但它看起来像这样:

create or replace procedure DEVOPS_DBCUPDATE( ... ) is
    pragma  autonomous_transaction;
begin
    update your_table
    set ....
    commit; 
end;

过程中的COMMIT会将更改保留到您的表中,但不会在外部事务中保存任何内容。因此,EXCEPTION块中的rollback仍会将插入反转到HS表中。

如果使用得当,自主交易非常有用,但很容易误用它们。这种情况 - 发生异常或回滚时的持久性日志记录 - 是它们的主要用例。但一般情况下,请谨慎使用:滥用自治事务很容易,最终导致数据库损坏。有更多信息in the Oracle documentation

答案 2 :(得分:0)

DECLARE部分中的错误引发不会由该块的EXCEPTION部分处理。因此,在BEGIN

之后初始化变量通常更安全
DECLARE  
  DBCID INT;
  CNT INT;  
BEGIN  
  DBCID := 'xxx';
  ...
EXCEPTION
  WHEN OTHERS THEN
     ... -- The assignment will be caught here
END;