【问题标题】:What's wrong with this PL/SQL Trigger?这个 PL/SQL 触发器有什么问题?
【发布时间】:2022-01-21 10:46:12
【问题描述】:

我有这张表,我想在Magazine 上创建一个触发器,如果​​插入的Magazine 的名称是VoguePeople,则验证“插入后” .

如果不是其中之一,则会被删除。

表:

  • 杂志(ISBN、MAG_NOM、PRIX_Mois);

我的触发器:

CREATE OR REPLACE TRIGGER TMag
  AFTER INSERT ON Magazine
  FOR EACH ROW
DECLARE
  e EXCEPTION;
BEGIN
  IF :new.mag_nom != 'Vogue' or :new.mag_nom != 'People' THEN
     DELETE Magazine WHERE ISBN = :new.ISBN;
    RAISE e;
  END IF;
EXCEPTION
  WHEN e THEN
    DBMS_OUTPUT.PUT_LINE('nom mag incorrecte');
END;

但问题是我的老师告诉我的:

这并不适合所有情况

我不知道那是什么意思,你能帮我改进一下这个触发器吗?

这对我来说似乎是正确的,我做错了什么?

【问题讨论】:

  • 这个触发器不合适,因为它根本不正确。你应该有ORA-04091: table <table name> is mutating, trigger/function may not see it。您可以为此使用check 约束,它更清晰。
  • @astentx 我只是一个初学者,所以我不能 100% 理解你。感谢您的帮助。

标签: sql oracle plsql triggers


【解决方案1】:

你不需要使用DML,将触发器转换成这个

CREATE OR REPLACE TRIGGER TMag
  AFTER INSERT ON Magazine
  FOR EACH ROW
BEGIN
  IF :new.mag_nom NOT IN ('Vogue','People') THEN
    RAISE_APPLICATION_ERROR(-20202,'nom mag incorrecte !');
  END IF;
END;
/

在这种情况下,由于在触发器的主体中使用了创建触发器的表,因此您会得到 table is mutating 错误。

此外,添加检查约束比创建触发器要好得多

ALTER TABLE abc
ADD CONSTRAINT cc_mag_nom
  CHECK (mag_nom IN ('Vogue','People'));

【讨论】:

  • 谢谢!你能解释一下我做错了什么或者我应该对我的代码做得更好吗?再次感谢:)
  • 不客气@Maoane,正如我所说,由于在同一个表上同时操作,使用触发器主体中的表会引发变异表错误,使用触发器可能会产生维护这样你就应该让它永远有效。而是在表的定义中使用检查约束。
猜你喜欢
  • 2012-04-26
  • 2011-08-06
  • 2017-09-14
  • 2011-08-28
  • 1970-01-01
  • 1970-01-01
  • 2013-12-06
  • 2011-08-16
相关资源
最近更新 更多