我想在一个名为 Tables_History 的表中记录所有表更改,每个表都有一个触发器,并且根据列的类型没有解决列名明确性。因为我有50张桌子可以支持不同的项目。许多开发人员可能会更改表的结构。所以我无法解决列名明显。这是对Tables_History的辩护:
create table Tables_History
(
user_id VARCHAR2(10) not null,
change_date DATE not null,
table_name VARCHAR2(100) not null,
column_name VARCHAR2(100) not null,
primary_key_id INTEGER not null,
old_number NUMBER,
new_number NUMBER,
old_string VARCHAR2(900),
new_string VARCHAR2(900),
old_date DATE,
new_date DATE,
...
.
);
如果有任何方法可以访问:触发器中的新列值,方法是将列名称作为参数而不是标准方式(:new.column_name )。这样的事情(:new ['column_name'] )。
这是我对一个表的理想触发器(然后我可以复制+粘贴其他表的触发器,只更改几个参数:-D):
create or replace trigger Audit_TableName
before update on TableName
for each row
declare
v_query varchar(32767);
UserCode varchar(10);
begin
SELECT sys_context('USERENV', 'CLIENT_IDENTIFIER')
INTO UserCode
FROM DUAL;
FOR getrec IN (SELECT column_name, data_type
FROM all_tab_columns
WHERE table_name = 'TableName'
AND owner = 'MEHRAN'
AND data_type <> 'BLOB') LOOP
if Updating(getrec.column_name) then
if getrec.data_type = 'NUMBER' then
v_query := 'insert into Tables_History(user_id,change_date,table_name,column_name,primary_key_id,,,OLD_NUMBER, NEW_NUMBER)'
||'values('..,..,..,..||:old[getrec.column_name]||','||:new[getrec.column_name]||')';
else if getrec.data_type = 'VARCHAR2' then
v_query := 'insert into Tables_History(...,...,... OLD_VARCHAR, NEW_VARCHAR)'
||'values(...,...,..'||:old[getrec.column_name]||','||:new[getrec.column_name]||')';
...
.
.
end if;
EXECUTE IMMEDIATE v_query;
end if;
END LOOP;
end Audit_TableName;
答案 0 :(得分:2)
你不能这样做。您可以编写存储过程以生成静态引用新/旧值的触发器:https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:59412348055
答案 1 :(得分:0)
我认为(没有第一手经验)Flashback Data Archive可以做你想要的,如果你正在使用Oracle11或更高版本。