【发布时间】:2015-06-26 18:41:50
【问题描述】:
我们的要求是,如果表中的任何一个列名正在更新,我们需要在另一个表中插入列名,所以我写了这段代码
CREATE OR REPLACE TRIGGER Test AFTER
UPDATE ON XX_table
FOR EACH Row
BEGIN FOR C IN
(SELECT column_name
FROM User_Tab_Columns
WHERE Upper(Table_Name) = 'XX_table_name' ORDER BY column_id ASC)
LOOP
IF Updating (c.column_name)
THEN
INSERT INTO Xx_Trigger_table (Rt_Id ,Updated_Column ,updated_status) VALUES(:Old.Rt_Id,C.Column_Name,'Y');
END IF;
END LOOP;
END;
现在客户端需要 XX_Trigger_Table 中的旧值和新值。我无法写入
INSERT INTO Xx_Trigger_table (Rt_Id ,Updated_Column ,updated_status,old_value, new_value) VALUES(:Old.Rt_Id,C.Column_Name,'Y',:old.c.column_name,:new.c.column_name);
请建议我在表格中插入新旧值。 提前致谢。
【问题讨论】:
-
这是一个奇怪的要求。为什么在审计表中需要
column name?您希望将修改后的行插入到带有timestamp列的审计表中。 -
是的,这是客户的奇怪要求。但是我们需要列名用于其他交易目的。如果你能帮助我,那就太好了。
-
然后告诉客户什么不是好的设计。对于审计,有许多更新的方法。
Fine Grained Auditing是一个很好的功能。否则,应该按照我建议的方式实施旧的触发方法。您需要一个审计表,其所有列都与基表类似,还有其他列,例如 id 列作为 PK,标识符列以了解它是否是insert, update or delete,以及timestamp栏目。 -
您不能像那样动态地引用新/旧伪行中的列名(我很惊讶更新子句允许它,真的)。如果您确定要使用此审计结构,那么您将必须明确且单独地测试每个列名,而不是循环测试,这意味着您列出每个列名。如果您担心列数,可以从数据字典中动态创建触发代码。另请注意,
updating表示该列被引用,不一定是该值实际发生了变化。 -
作为替代方案,this old answer 显示了一种使用更常见的审计表/触发器方法的方法,
unpivot可以查看更改的值;你可以做一些类似的事情,也许是为了满足客户的要求,也许?
标签: oracle plsql triggers oracle11g