触发器中的标识符无效
Posted
技术标签:
【中文标题】触发器中的标识符无效【英文标题】:Invalid Identifier within a Trigger 【发布时间】:2019-08-20 22:46:53 【问题描述】:我不断得到: PL/SQL: ORA-00904: "NEWROW"."ACCOUNT_NUM": 无效标识符
设置服务器输出;
--OVERDRAFT TRIGGER
create or replace trigger overdraft_trigger
after update on checking_acc
REFERENCING NEW AS newrow
fOR EACH ROW
when (newrow.balance < 0)
Begin
update checking_acc
set overdraft_amount = newrow.balance
where (newrow.account_num = checking_acc.account_num);
end;
/
见上
触发器将 overdraft_amount 设置为 newrow.balance。
【问题讨论】:
尝试在触发器内更新触发真正触发器的同一个平板电脑注定会失败。将其设置为前触发器并将新行值直接更改为您要提交的任何内容。我很震惊,因为它是如此简单,不需要触发器。你怎么用了一个? 分配需要触发器。当它是更新值时,如何直接分配 newrow 值? 同意上面的 Caius,但 newrow 也需要 : 在它前面,这就是您收到特定错误的原因。 【参考方案1】:如果你这样做。在 UPDATE 触发器之前,您可以直接设置新值并将它们写入表中:
SET SERVEROUTPUT ON;
--OVERDRAFT TRIGGER
CREATE OR REPLACE TRIGGER overdraft_trigger
BEFORE UPDATE on checking_acc
fOR EACH ROW
WHEN (newrow.balance < 0)
BEGIN
:new.overdraft_amount := :new.balance;
END;
除非要重命名伪行,否则不需要 REFERENCING 子句
您不会在 WHEN 中使用冒号作为 NEW 前缀,但您会在过程主体中使用冒号作为前缀
避免运行选择/插入/更新/ 删除针对触发触发器的同一表的语句 - 如果这样做,您可能最终会遇到“表正在变异,触发器可能看不到它”错误。 Oracle 试图向您表明您在表中引用的数据可能已更改也可能未更改,这可能会导致您的数据不一致
尽可能避免使用行级触发器,因为如果很多行受到影响,它们的性能不如语句级触发器。数据库可以更好地批量处理事情,而且确实像 SQLServer 这样的一些数据库甚至没有行级触发器,这迫使您从数据集的角度考虑所有事情。归根结底,大多数数据库的触发器实现都是特定于供应商的。您还会发现大多数 DBA 总体上不喜欢触发器,并且更愿意将代码逻辑放入存储过程中。触发器可以方便快速修复错误导致表中的数据错误,但通常在生产系统上避免使用,因为它们相对隐藏/神奇 - 开发人员忘记了它们,然后花时间想知道为什么它们发送到表中的值x 未显示为已发送
精美的手册有很多关于触发器的重要信息 - https://docs.oracle.com/cd/E11882_01/appdev.112/e25519/triggers.htm
2 天指南中还有更易读的摘要 - https://docs.oracle.com/database/121/TDDDG/tdddg_triggers.htm
【讨论】:
以上是关于触发器中的标识符无效的主要内容,如果未能解决你的问题,请参考以下文章