触发器中的标识符无效

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

【讨论】:

以上是关于触发器中的标识符无效的主要内容,如果未能解决你的问题,请参考以下文章

Oracle触发器错误 - 无效的标识符

ORA-00904: 无效标识符 00904. 00000 - "%s: 无效标识符"

oracle 忽略子查询中的无效标识符错误

swift 4 中的应用内购买无效的产品标识符

过程中 UPDATE oracle 中的变量:标识符无效

标识符4中的字符无效