在 Oracle 触发器中动态评估伪记录 (:OLD, :NEW)
Posted
技术标签:
【中文标题】在 Oracle 触发器中动态评估伪记录 (:OLD, :NEW)【英文标题】:Dynamically Evaluate Pseudo Records (:OLD, :NEW) in Oracle Trigger 【发布时间】:2015-01-27 18:54:03 【问题描述】:问题:我有一个客户可以添加列的表格。根据客户的疯狂程度,该表可能包含数百列不同数据类型的列。我需要针对此表部署一个 AFTER UPDATE 触发器,以便在另一个表中为每个已更改的列值插入一行 。
示例:
Table_A,第 1 行:Key_Value=1,Col1=123,Col2="foo"...Coln="bar" 变成 表_B,第 1 行:Key_Value=1,ColName="Col1",ColValue=123 表_B,第 2 行:Key_Value=1,ColName="Col2",ColValue="foo" Table_B,第 3 行:Key_Value=1,ColName="Coln",ColValue="bar"由于我不知道他们可能创建哪些列并且此触发器必须与应用程序一起部署,我需要动态评估 OLD 与 NEW 伪记录 (if :new.columns[1] != :old.columns[1] then...
) 以查看发生了什么变化并仅记录更改的列.我能找到的唯一示例需要明确引用伪记录中的列 (if :new.col1 != :old.col1 then...
)。
问题:有没有办法在 Oracle 中做到这一点?
注意事项:不,这不是出于审计目的,所以我不能使用 Oracle 的内置审计。不,我们不会重写我们的应用程序,因为您知道如何做得更好,这是它需要以更好或更坏的方式工作。
欢迎任何有用的 cmets。并非所有刻薄的 DBA 胡言乱语。提前致谢。
【问题讨论】:
您能否在添加每一列后通过模式 DDL 触发器重新生成触发器?然后可以从数据字典中生成一次检查和插入。 如果这是不可能的,那是我的“B计划”。 是时候实施B计划然后*8-) 【参考方案1】:没有。您不能动态引用 :new
或 :old
伪记录中的列。
您最接近的可能是编写代码,通过查询数据字典并对伪记录中的列进行静态引用来动态生成整个触发器主体。但是,每次从表中添加或删除列时,都需要运行该代码。通常,这将作为正常发布管理的一部分来完成。如果您说人们在未经过发布过程的情况下从该表中添加和删除列,您可以编写一个 DDL 触发器,该触发器通过 dbms_job
提交作业,该触发器调用重建触发器的过程。这将是很多移动的部分,当不可避免地出现问题时,排除故障会很痛苦,但如果您不接受实现功能的替代方法,那么您将不得不忍受这种复杂性。
【讨论】:
我可以使用 EXECUTE IMMEDIATE 从 DDL 触发器中直接运行该触发器“创建或替换”吗?我意识到这可能不是理想的情况,但我们对这些环境没有太多控制权,我不知道我是否可以确定我们的用户将有权创建作业, @relucantdba - 不。您不能在触发器中提交(或回滚)。所以你不能从触发器发出 DDL。此外,您需要在 DDL 完成后运行create or replace trigger
,以便数据字典反映新列。请注意,除了拥有触发器的用户需要调用dbms_job
的权限(dbms_scheduler
在此处无法工作,因为提交作业已提交)之外,数据库还需要允许运行足够数量的后台作业以确保您提交的作业实际运行。
非常感谢您的帮助。非常感谢!以上是关于在 Oracle 触发器中动态评估伪记录 (:OLD, :NEW)的主要内容,如果未能解决你的问题,请参考以下文章