SQL / Oracle 10g - 触发器问题

时间:2012-03-20 09:09:47

标签: sql oracle

在创建语句级别触发器时,我遇到了SQL / Oracle 10g的问题。我试图用这个触发器实现的是在学生注册时删除一个实用课程。 5.以下是我写的:

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

仍然会发生变异表

2 个答案:

答案 0 :(得分: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。物化视图处理此问题以及变异表错误。

答案 1 :(得分:1)

删除FOR EACH ROW

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