【问题标题】:SQL trigger compiles correctly but throws errorSQL 触发器编译正确但抛出错误
【发布时间】:2016-10-16 13:19:24
【问题描述】:

我正在尝试创建一个触发器,当添加新行时,该触发器将值从同一表的一列(“notubes”)复制到同一表的另一列(“notubesleft”)。触发器编译正确但是当我插入一个新行,它会引发错误。

我的触发器是:

create or replace TRIGGER NOTUBESLEFT_INSERT_TRIGGER    
AFTER INSERT ON SAMPLES FOR EACH ROW BEGIN 
update samples
 set notubesleft = (select notubes from samples where sampleid = :new.sampleid);
 END;

当我尝试提交新行时出现错误:

保存对表“APEX_WS_PROMETHEUS”的更改时出错。“SAMPLES”:
第 10 行:ORA-04091:表 APEX_WS_PROMETHEUS.SAMPLES 正在变异, 触发器/函数可能看不到它
ORA-06512:在“APEX_WS_PROMETHEUS.NOTUBESLEFT_INSERT_TRIGGER”,第 2 行 ORA-04088: 执行触发器“APEX_WS_PROMETHEUS.NOTUBESLEFT_INSERT_TRIGGER”时出错
ORA-06512: 在第 1 行

我问了一个新问题,因为我可以找到有关如何构造触发器的 PL/SQL 代码的解决方案,但我不知道为什么它不起作用。

谢谢。

【问题讨论】:

  • 您为什么要尝试使用插入后触发器来执行此操作?
  • 因为我认为我首先需要在表中插入值,然后才能使用它们填充另一列。这是我的第一个触发器。

标签: oracle oracle-sqldeveloper


【解决方案1】:

您不能(轻松)使用行级触发器查询要插入的表。但是您根本不应该查询表,也不应该使用插入后触发器来执行此操作。改为使用插入前触发器;您可以从:NEW 伪记录中获取和设置值:

CREATE OR REPLACE TRIGGER NOTUBESLEFT_INSERT_TRIGGER    
BEFORE INSERT ON SAMPLES FOR EACH ROW
BEGIN 
  :new.notubesleft := :new.notubes;
END;

【讨论】:

    【解决方案2】:

    您遇到了变异表问题。有一个限制,您不能查询在 FOR EACH ROW 触发器中发生变异的表

    Trigger Restrictions on Mutating Tables

    如果您必须更新变异表,您可以绕过这些限制 通过使用临时表、PL/SQL 表或包变量。为了 例如,代替更新 原始表,导致变异表错误,您可能会使用两个 触发器——更新临时表的 AFTER 行触发器,以及 AFTER 语句触发器,它使用 临时表中的值。

    【讨论】:

    • 感谢您的帮助。我也想知道 FOR EACH ROW 是否正确。我的目标是只为插入的新行运行触发器。我希望用户一次只能插入 1 行。
    猜你喜欢
    • 2012-04-27
    • 2014-01-04
    • 2016-03-21
    • 2020-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-09
    • 1970-01-01
    相关资源
    最近更新 更多