【问题标题】:SQL/Oracle 10g - Issue with triggersSQL/Oracle 10g - 触发器问题
【发布时间】:2012-04-04 18:02:53
【问题描述】:

在创建语句级触发器时,我遇到了 SQL/Oracle 10g 的问题。我试图用这个触发器实现的是在学生注册量

CREATE OR REPLACE TRIGGER delete_prac
AFTER UPDATE ON studEnrol
BEGIN
   DELETE FROM pracList
   WHERE Practical IN (
   SELECT Practical
   FROM studEnrol
   GROUP BY Practical
   HAVING COUNT(Practical) < 5);
END delete_prac;

我得到的错误是:

ORA-04091: pracList table is mutating, trigger/function may not see it

我已经调查了这个错误,提出的建议是包含 :new 和 :old 关键字,但我不知道该怎么做。

感谢任何帮助!

谢谢。

编辑:忘记添加正在变异的表,它是 pracList 表 EDIT2:将其更改为语句级触发器,变异表仍然出现在 pracList 中

【问题讨论】:

  • 您在 pracList 上还有其他触发器吗?
  • 在表上显示 ddl:pracList、studEnrol

标签: sql oracle


【解决方案1】:

删除FOR EACH ROW

那么你的触发器只会在更新行后运行一次,并且表不会发生变异。

【讨论】:

  • 不起作用。我尝试将 studEnrol 表中的学生注册从一个实际更改为另一个,但错误仍然存​​在。例如,有 5 名学生注册了物理,然后我编辑了一名正在做物理的学生做数学,触发器应该从 praclist 中删除实用。
【解决方案2】:

这可能正如 Florin Ghita 所建议的那样发生,因为您在 praclist 上有一个触发器。当您更新studenrol 时,您会尝试从praclist 中删除。此行为触发另一个触发器,这会导致您的问题。引发此错误是为了提供数据的读取一致视图。作为Tom Kyte says,此错误可能表明您的架构或逻辑存在缺陷,您应该重新考虑其中一个或两者。

此外,一般来说,您正在执行的触发器中的全表扫描是一个坏主意TM。根据表的大小,您最终可能会在 studlist 上的每次更新上花费 1 秒或 2 小时,这远非最佳。

在不知道您的架构或praclist 上的触发器的情况下很难确定,但是,在您的情况下,似乎有一个“out”。完全放弃这个触发器;没有必要。

在praclist 上创建一个materialized view,为您提供所需的数据。无论如何,不​​断地删除和插入值到praclist 中是没有意义的,因为您只能拥有一个视图来保持此处的信息不断更新。以下查询应该这样做:

select p.*
  from praclist p
  join ( select practical
           from studenrol
          group by practical
         having count(*) >= 5 ) s
    on p.practical = s.practical

顺便说一句,如果注册的学生人数突然变得足以进行实际操作,则您当前的触发器不允许插入 praclist。物化视图可以解决这个问题以及变异表错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-28
    • 2020-07-15
    • 1970-01-01
    • 2014-06-19
    • 2011-07-29
    • 1970-01-01
    • 1970-01-01
    • 2014-06-21
    相关资源
    最近更新 更多