Oracle PL/SQL变异触发器-替代方案?
下面的代码用于在插入新记录时触发,并用于更改新记录的字段,但在尝试插入时出现了一个变异错误。我能做些什么来解决这个问题Oracle PL/SQL变异触发器-替代方案?,oracle,plsql,triggers,Oracle,Plsql,Triggers,下面的代码用于在插入新记录时触发,并用于更改新记录的字段,但在尝试插入时出现了一个变异错误。我能做些什么来解决这个问题 CREATE OR REPLACE TRIGGER trig_auto_rating_desc AFTER INSERT ON reviews FOR EACH ROW DECLARE vn_rating NUMBER(1); vc_rating_description reviews.rating_description%TYPE := ''; BEGIN
CREATE OR REPLACE TRIGGER trig_auto_rating_desc
AFTER INSERT ON reviews
FOR EACH ROW
DECLARE
vn_rating NUMBER(1);
vc_rating_description reviews.rating_description%TYPE := '';
BEGIN
vn_rating := :NEW.overall_rating;
CASE vn_rating
WHEN 1 THEN vc_rating_description := 'VERY POOR';
WHEN 2 THEN vc_rating_description := 'POOR';
WHEN 3 THEN vc_rating_description :='OKAY';
WHEN 4 THEN vc_rating_description := 'GOOD';
WHEN 5 THEN vc_rating_description := 'VERY GOOD';
ELSE dbms_output.put_line('NO SUCH REVIEW');
END CASE;
dbms_output.put_line(vn_rating || ' = ' || vc_rating_description);
UPDATE reviews SET rating_description = vc_rating_description WHERE review_id = :NEW.review_id;
END trig_auto_rating_desc;
/
当一条语句导致触发触发器,并且该触发器引用导致该触发器的表时,就会发生一个变异表。避免此类问题的最佳方法是不要使用触发器,或者您可以尝试以下方法:
- 将触发器更改为后触发器
- 将其从行级触发器更改为语句级触发器
- 转换为复合触发器
- 使触发器具有自治性,其中包含提交
- 将触发器更改为后触发器
- 将其从行级触发器更改为语句级触发器
- 转换为复合触发器
- 使触发器具有自治性,其中包含提交
那就去办你的案子吧
CREATE OR REPLACE TRIGGER trig_auto_rating_desc
BEFORE INSERT
ON REVIEWS
REFERENCING NEW AS New OLD AS Old
FOR EACH ROW
DECLARE
vn_rating NUMBER(1);
vc_rating_description reviews.rating_description%TYPE := '';
BEGIN
vn_rating := :NEW.overall_rating;
CASE vn_rating
WHEN 1 THEN vc_rating_description := 'VERY POOR';
WHEN 2 THEN vc_rating_description := 'POOR';
WHEN 3 THEN vc_rating_description :='OKAY';
WHEN 4 THEN vc_rating_description := 'GOOD';
WHEN 5 THEN vc_rating_description := 'VERY GOOD';
ELSE vc_rating_description := 'Invalid value';
--you will never see dbms_output from a trigger
--ELSE dbms_output.put_line('NO SUCH REVIEW');
END CASE;
:new.rating_description := vc_rating_description;
END trig_auto_rating_desc;
如果要逐行修改值,则无需在触发器内执行更新。
那就去办你的案子吧
CREATE OR REPLACE TRIGGER trig_auto_rating_desc
BEFORE INSERT
ON REVIEWS
REFERENCING NEW AS New OLD AS Old
FOR EACH ROW
DECLARE
vn_rating NUMBER(1);
vc_rating_description reviews.rating_description%TYPE := '';
BEGIN
vn_rating := :NEW.overall_rating;
CASE vn_rating
WHEN 1 THEN vc_rating_description := 'VERY POOR';
WHEN 2 THEN vc_rating_description := 'POOR';
WHEN 3 THEN vc_rating_description :='OKAY';
WHEN 4 THEN vc_rating_description := 'GOOD';
WHEN 5 THEN vc_rating_description := 'VERY GOOD';
ELSE vc_rating_description := 'Invalid value';
--you will never see dbms_output from a trigger
--ELSE dbms_output.put_line('NO SUCH REVIEW');
END CASE;
:new.rating_description := vc_rating_description;
END trig_auto_rating_desc;
我已经把它作为后触发器了,所以我不明白为什么会出现这个错误,它会在插入行后更新行,除非它在触发器完成后才真正插入?您可以尝试使用自治事务自治事务不是这里的解决方案(而且,总的来说,对于任何触发器)@Globin>您需要了解触发器。我建议看一看,您可以看到
后触发器无法更改新字段值,因为触发语句在触发器触发之前运行。
。换句话说,您可以在插入行之前更改插入的值,但一旦插入了行,就到此为止。正如我上面所说,在触发器之前使用,或者将更改作为insert语句的一部分。@Boneist再次感谢您的建议,它工作得很好。我已经将它作为后触发器使用,所以我不明白为什么会出现此错误,它会在插入行之后更新行,除非它在触发器完成后才真正插入?您可以尝试使用自治事务自治事务不是这里的解决方案(总体而言,对于任何触发器)@Globin>您需要了解触发器。我建议看一看,您可以看到后触发器无法更改新字段值,因为触发语句在触发器触发之前运行。
。换句话说,您可以在插入行之前更改插入的值,但一旦插入了行,就到此为止。正如我上面所说的,在触发器之前使用,或者在insert语句中进行更改。@Boneist再次感谢您的建议,它工作得很好感谢您的回复,我收到一个错误:new.rating\u description=vc\u rating\u description,这是不是意味着“:”?我说出来还是有错误“无法更改此触发器类型的新值“在线路上出错1@theglobin这是因为您正在使用AFTER
触发器。在触发器之前将其切换到,它应该可以工作。或者,您也可以在insert语句本身中执行case语句。@Boneist谢谢!这就是解决方案,一切都很完美:)感谢您的回复,我在这行上收到了一个错误:new.rating_description=vc_rating_description,这是不是意味着“:”?“我仍然收到一个错误,说它“无法更改此触发器类型的新值”在线路上出错1@theglobin这是因为您正在使用AFTER
触发器。在触发器之前将其切换到,它应该可以工作。或者,您也可以在insert语句本身中执行case语句。@Boneist谢谢!这就是解决方案,一切都很完美:)