PL/SQL触发器抛出异常时行仍被插入的原因咨询
为什么你的触发器抛出异常后仍会插入行?
首先,咱们得搞清楚Oracle触发器里RETURN语句的作用——在BEFORE触发器中,RETURN只是终止触发器本身的PL/SQL块执行,但不会中断触发它的主INSERT操作。这就是为什么你看到错误信息打印出来了,但行还是被插入到DOCKING表的原因。
而你尝试用EXIT命令失败,是因为EXIT是用于循环(比如FOR/WHILE循环)里跳出循环的语句,触发器的PL/SQL块不是循环结构,所以编译器会报错,自然没法正常工作。
正确的解决方案:抛出未处理的异常来阻止插入
要阻止主INSERT操作,你需要让触发器抛出一个未被捕获的异常,这样Oracle会自动终止当前的INSERT事务,不会插入行。有两种常见的实现方式:
方式1:移除自定义异常的捕获,让异常向上传播
直接去掉EXCEPTION块里对EX_WEIGHT和bad_date的捕获,这样当触发这些异常时,Oracle会直接终止INSERT操作:
CREATE or REPLACE TRIGGER t_ships BEFORE INSERT ON DOCKING FOR EACH ROW DECLARE cweight SHIPS."cargo weight"%TYPE; cap PIERS.capacity%TYPE; EX_WEIGHT EXCEPTION; bad_date EXCEPTION; BEGIN SELECT s."cargo weight" into cweight from SHIPS s where s.SID = :NEW.SID; SELECT p.capacity into cap from PIERS p where p.PID = :NEW.PID; IF cweight>cap THEN RAISE ex_weight; ELSIF :NEW."arrival date">:NEW."departure date" THEN RAISE bad_date; END IF; UPDATE PIERS set "Total ships" = "Total ships" + 1 WHERE PID = :NEW.PID; END;
这种方式下,当触发异常时,Oracle会抛出默认的异常信息,同时阻止插入。
方式2:捕获异常后,用RAISE_APPLICATION_ERROR抛出自定义错误
如果你想保留自定义的错误提示,同时阻止插入,可以在EXCEPTION块里用RAISE_APPLICATION_ERROR抛出一个带有错误码的异常(错误码需要在-20000到-20999之间):
CREATE or REPLACE TRIGGER t_ships BEFORE INSERT ON DOCKING FOR EACH ROW DECLARE cweight SHIPS."cargo weight"%TYPE; cap PIERS.capacity%TYPE; EX_WEIGHT EXCEPTION; bad_date EXCEPTION; BEGIN SELECT s."cargo weight" into cweight from SHIPS s where s.SID = :NEW.SID; SELECT p.capacity into cap from PIERS p where p.PID = :NEW.PID; IF cweight>cap THEN RAISE ex_weight; ELSIF :NEW."arrival date">:NEW."departure date" THEN RAISE bad_date; END IF; UPDATE PIERS set "Total ships" = "Total ships" + 1 WHERE PID = :NEW.PID; EXCEPTION WHEN EX_WEIGHT THEN RAISE_APPLICATION_ERROR(-20001, 'Weight exceeds capacity'); WHEN bad_date THEN RAISE_APPLICATION_ERROR(-20002, 'Arrival date is after departure date'); END;
这样做的好处是,你可以自定义清晰的错误信息,同时Oracle会因为这个异常终止INSERT操作,不会插入不符合条件的行。
额外提醒
注意你的UPDATE PIERS语句:只有当检查通过时才会执行这个更新,这是正确的逻辑——因为如果检查失败,异常会终止触发器,这个更新也不会执行,避免了PIERS表的Total ships字段被错误累加。
内容的提问来源于stack exchange,提问作者mrpink121
相关产品推荐
相关产品推荐

