执行触发器期间发生未知错误

时间:2018-08-28 00:52:18

标签: database oracle plsql triggers

我已经设置了一个插入/更新触发器,以防止一个雇员同时存在于两个表中。它可以很好地捕获非法插入/更新,但在测试带有非法插入/更新的触发器时,我还会收到另一个错误报告。

这是我的代码:

CREATE OR REPLACE TRIGGER check_foobar
BEFORE INSERT OR UPDATE OF VarX ON FOOBAR
FOR EACH ROW
DECLARE
    counter NUMBER(38);
BEGIN  
    SELECT count(*)
    INTO counter
    FROM BARFOO
    WHERE VarX = :NEW.VarX
    GROUP BY VarX;

IF counter > 0 THEN 
    RAISE_APPLICATION_ERROR(-20001, 'This is an illegal insertion/update');
    END IF;

EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('TEST');

END;
/

我不确定错误ORA-06512和ORA-04088:

SQL> INSERT INTO DRIVER VALUES(2,  10345, 'AVAILABLE');

Error starting at line : 26 File @test.sql
In command -
INSERT INTO FOOBAR VALUES(2)
Error report -
ORA-20001: This is an illegal insertion/update
ORA-06512: at "HR.CHECK_FOOBAR", line 11
ORA-04088: error during execution of trigger 'HR.CHECK_FOOBAR'

当我为select语句添加异常处理程序时,我的触发器会停止正常工作,并且不会阻止非法插入。但是可以防止执行错误。

更新:我给触发器添加了一个group by和一个例外,因此现在触发器仍然可以与例外处理程序一起使用,但是错误ORA-06512和ORA-04088仍然伴随着非法的插入/更新。

错误中提到的第11行是

GROUP BY VarX;

任何建议将不胜感激。

2 个答案:

答案 0 :(得分:3)

这里没有问题,它按预期运行。

Error starting at line : 26 File @test.sql
In command -
INSERT INTO FOOBAR VALUES(2)

这是指脚本中具有INSERT语句的行。告诉您此时已引发异常。

Error report -

这显示了错误堆栈:

ORA-20001: This is an illegal insertion/update

这是引发的实际异常。

ORA-06512: at "HR.CHECK_FOOBAR", line 11
ORA-04088: error during execution of trigger 'HR.CHECK_FOOBAR'

这些是其他消息,它们只是告诉您最初在何处引发了异常,在这种情况下,您可能希望在第11行的触发器RAISE_APPLICATION_ERROR中。请注意,触发器的行号是指触发器的可执行部分,因此在您的情况下,DECLARE是行1。

答案 1 :(得分:-1)

ORA-04088错误表示触发器具有未处理的异常。您正在提出一个应用程序错误,但是没有处理。您需要按照以下说明处理此异常。

CREATE OR REPLACE TRIGGER check_foobar
BEFORE INSERT OR UPDATE OF VarX ON FOOBAR
FOR EACH ROW
DECLARE
    counter NUMBER(38);
    BEGIN  
       SELECT count(*)
       INTO counter
       FROM BARFOO
       WHERE VarX = :NEW.VarX
       GROUP BY VarX;

    IF counter > 0 THEN 
       RAISE_APPLICATION_ERROR(-20001, 'This is an illegal insertion/update');
    END IF;

EXCEPTION 
   WHEN NO_DATA_FOUND THEN 
      DBMS_OUTPUT.PUT_LINE('TEST');
   WHEN OTHERS THEN
      IF SQLCODE = -20001 THEN
        -- do some logging
        RAISE;
      ELSE
        -- do some logging and any other actions you feel are needed.   Then depending on needs you can raise or not.

      END IF;
END;
/