Oracle 触发器中需要列名、旧值和新值
我们的要求是,如果表中的任何1个列名正在更新,我们需要在另一个表中插入列名,所以我编写了这段代码Oracle 触发器中需要列名、旧值和新值,oracle,plsql,triggers,oracle11g,Oracle,Plsql,Triggers,Oracle11g,我们的要求是,如果表中的任何1个列名正在更新,我们需要在另一个表中插入列名,所以我编写了这段代码 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
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_触发器_表中的新值。我无法写入
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);
请建议我在表中插入新值和旧值。
提前感谢。如果您采用这种方法,就像@Alex Poole建议的那样,您必须包括所有要记录的列。请参阅本程序及其输出
CREATE OR REPLACE TRIGGER Test1 AFTER
UPDATE ON TESTEMP
FOR EACH Row
BEGIN FOR C IN
(SELECT column_name
FROM User_Tab_Columns
WHERE Upper(Table_Name) = 'TESTEMP' ORDER BY column_id ASC)
LOOP
IF Updating (c.column_name) then
IF (c.column_name='EMPNO') then
INSERT INTO test_audit (col_name,old_val,new_val,upd_stat) VALUES (C.column_name,:Old.empno,:New.empno,'Y');
ELSIF
(c.column_name='ENAME') then
INSERT INTO test_audit (col_name,old_val,new_val,upd_stat) VALUES (C.column_name,:Old.ENAME,:New.ENAME,'Y');
ELSIF
(c.column_name='MGR') then
INSERT INTO test_audit (col_name,old_val,new_val,upd_stat) VALUES (C.column_name,:Old.MGR,:New.MGR,'Y');
END IF;
END IF;
END LOOP;
END;
SQL> select * from testemp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
7369 SMITH CLERK 7902 17-DEC-80 800 20
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30
7566 JONES MANAGER 7839 02-APR-81 2975 20
SQL> select * from test_audit;
no rows selected
SQL> update testemp set empno=6677 , ename='JUPITER' where empno=1234;
1 row updated.
SQL> COMMIT;
Commit complete.
SQL> select * from test_audit;
COL_NAME OLD_VAL NEW_VAL U
---------- ---------- ---------- -
EMPNO 1234 6677 Y
ENAME SMITH JUPITER Y
这是一个奇怪的要求。为什么在审核表中需要
列名
?您只希望将修改后的行插入到带有时间戳
列的审计表中。但出于其他事务目的,我们需要列名。如果你能帮助我,那就太好了。然后告诉客户这不是一个好的设计。对于审计,有许多更新的方法<代码>细粒度审计是一个很好的特性。否则,旧的触发方法应该按照我建议的方式实现。您需要一个审计表,所有列都与基表相似,还需要其他列,如id列作为PK,标识符列以了解它是否是插入、更新或删除
,以及时间戳
列。您不能像这样动态引用新/旧伪行中的列名(我很惊讶更新条款允许它,真的)。如果您决定使用此审核结构,则必须显式地单独测试每个列名,而不是在循环中测试,这意味着您列出了每个列名。如果您担心列的数量,则可以从数据字典中动态创建触发器代码。还请注意,更新
意味着该列被引用,不一定是实际更改的值。作为替代方案,显示了一种使用更常见的审核表/触发器方法的方法,使用unpivot
查看更改的值;您可以执行类似的操作,也许在视图中,以满足客户的要求,也许?Anu解决了上述代码i的问题如果我们对表进行任何更改,那么我们也必须对触发器进行更改。是的,但是表结构多久会更改一次?