将触发器转换为复合触发器?

时间:2017-04-22 01:04:39

标签: sql oracle plsql triggers

如何将以下简单触发器转换为复合触发器,以避免ORA-04091 table is mutating error

CREATE OR REPLACE TRIGGER grades_before_update
BEFORE UPDATE OF grade_percent
ON grades
FOR EACH ROW
DECLARE
     grade_percent_var  NUMBER;
BEGIN
     SELECT  grade_percent
     INTO    grade_percent_var
     FROM    grades
     WHERE   student_id = :new.student_id;    

     IF (grade_percent_var > 100 OR grade_percent_var < 0) THEN
          RAISE_APPLICATION_ERROR(-20001, 'grade percent must be between 0 and 100');
     END IF;
END;
/

我问的原因是因为我每次使用UPDATE查询测试此触发器时都会这样:

UPDATE grades
SET grade_percent = 90
WHERE student_id = 1;

我得到ORA-04091 table is mutating error。我已经搜索过了,这个网站说我需要一个复合触发器来避免这个错误:

Using Triggers

但我不知道如何开始。

1 个答案:

答案 0 :(得分:2)

您不需要复合触发器,只需要检查当前值即可。该错误是因为您正在选择要更新的表,这是一个无效的操作(对于之前的触发器)。

所以你只需要像对<Window x:Class="WpfApp15.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp15" xmlns:controls="clr-namespace:WpfControlLibrary1;assembly=WpfControlLibrary1" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <Grid Background="Green"> <controls:PanelChoice /> </Grid> </Window> 一样访问该字段的值

这将是:

:new.student_id

无需声明任何变量或select语句。 IF (:NEW.grade_percent > 100 OR :NEW.grade_percent < 0) THEN RAISE_APPLICATION_ERROR(-20001, 'grade percent must be between 0 and 100'); END IF; :NEW.grade_percent命令中使用的值。