Oracle 异常未在触发器中捕获
Posted
技术标签:
【中文标题】Oracle 异常未在触发器中捕获【英文标题】:Oracle exception not caught in trigger 【发布时间】:2019-07-15 03:05:46 【问题描述】:我正在尝试捕获 ORA-02292 child record found
异常,而不是使用我自己的消息引发自定义异常。
这是我的简单触发器:
CREATE OR REPLACE TRIGGER modifOuSuppressionSucc
BEFORE DELETE OR UPDATE ON Succursale
FOR EACH ROW
BEGIN
IF DELETING THEN
UPDATE Projet SET NumSuccursale = NULL
WHERE NumSuccursale = :OLD.NumSuccursale;
ELSE
IF UPDATING AND :NEW.NumSuccursale!=:OLD.NumSuccursale THEN
UPDATE Projet SET NumSuccursale = :NEW.NumSuccursale
WHERE NumSuccursale = :OLD.NumSuccursale;
END IF;
END IF;
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20010, 'La modification ou la suppression d''une succursale n''est pas possible. Erreur '||SQLCODE||' -ERREUR- '||SQLERRM);
END;
当我尝试使用以下命令删除父表中的行时,Oracle 会引发 -02292 异常(这是正确的),但 WHEN OTHERS THEN
子句不会引发我的自定义异常。
DELETE Succursale WHERE NumSuccursale=4;
我收到标准的ORA-02292 child record found
消息:
Erreur commençant à la ligne: 48 de la commande -
DELETE Succursale WHERE NumSuccursale=4
Rapport d'erreur -
ORA-02292: violation de contrainte (HB691016.SYS_C003806517) d'intégrité - enregistrement fils existant
而不是我的-20010
自定义错误消息。
我需要改变什么才能让它正确?
【问题讨论】:
我试图重现您的场景,但无法重现。您能否在我的example 中分享可重现的示例 您只捕获触发代码引发的异常,此处抛出的实际异常与此触发代码无关。您可能应该验证与触发器中的约束(在 SUCCURSALE 表上)相关的数据完整性,如果不满足条件则抛出错误。 没有得到您在最后一条评论中所传达的内容 - 请参阅Example。没有触发器,它会抛出一个错误,WITH TRIGGER
,它不会抛出一个错误。如果您在谈论其他内容,请编辑 db fiddle 并分享已编辑的 db fiddle 的 URL
【参考方案1】:
触发器不适用于此。如果您必须在父表中删除不受您控制的删除,那么拥有FOREIGN KEY
并不是一个好设计。
您可以使用DEFERRABLE Clause 作为您的约束。这允许您在提交事务之前在单个语句中运行删除和更新。
ALTER TABLE Projet ADD CONSTRAINT fk_succurscale foreign key(NumSuccursale)
references Succursale(NumSuccursale) initially deferred deferrable
这是它如何工作的说明。
declare
l_del Succursale.NumSuccursale%TYPE := 3;
l_upd_from Succursale.NumSuccursale%TYPE := 4;
l_upd_to Succursale.NumSuccursale%TYPE := 3;
BEGIN
DELETE Succursale WHERE NumSuccursale=l_del;
UPDATE Projet SET NumSuccursale=NULL WHERE NumSuccursale=l_del;
COMMIT;--Constraint checking won't happen until this commit is issued.
UPDATE Succursale SET NumSuccursale=l_upd_to WHERE NumSuccursale=l_upd_from;
UPDATE Projet SET NumSuccursale=l_upd_to WHERE NumSuccursale=l_upd_from;
COMMIT;
END;
/
上述区块的DEMO。
【讨论】:
以上是关于Oracle 异常未在触发器中捕获的主要内容,如果未能解决你的问题,请参考以下文章
如果在更新触发之前未在 oracle 中进行更新,则新值与旧值相同
捕获到 SQL 异常。错误是:ORA-04098:触发器无效并且重新验证失败