本次需要批量編寫監控全數據庫表的trigger,記錄下變更的字段名和變更的值、表名、相對應的主鍵和做的操作(增刪改)。在自動生成腳本sql后,執行execute
immediate sql_str --date:2021-11-05
- 通過 || 拼接字符串。
- 通過user_cons_columns , user_constraints 來獲取表的主鍵。以CONSTRAINT_TYPE 選定主鍵類型,以TABLE_NAME綁定表名,從而獲取表的主鍵名,為后續拼接獲取表主鍵和主鍵值做准備。最后,將該表所有主鍵名存放於var_array (防止組合主鍵),后續能夠遍歷取出
- 通過表user_tab_columns 獲取表所有字段,后續拼接查看值的更新。
- 通過new.column <> old.column 來判斷前后值是否變更,如若變更,記錄下變更的值。
- if deleting,inserting,updating來判斷執行的操作。
- 最后,生成的trigger將向我們新建的存儲表插入執行的操作,變更的列名,變更的值以及主鍵,以便於我們檢索。
- 同理,可生成批量啟動和關閉trigger的腳本。
(1)首先獲取數據庫中所有表的表名
for tables_name in ( select table_name from user_tables ) loop
(2)根據約束表,獲取各表的主鍵--需求需要
for primary_key in ( select cu.COLUMN_NAME from user_cons_columns cu , user_constraints au where cu.constraint_name = au.CONSTRAINT_NAME and au.CONSTRAINT_TYPE = 'P' and au.TABLE_NAME= tables_name.table_name )loop i:=i+1; var_array(i):=primary_key.column_name; end loop;
(3)trigger在插入修改和刪除前觸發
-- the first set sql_str sql_str := 'create or replace trigger '||' task_for_link_'||tables_name.table_name|| ' before insert or update or delete'|| ' on '||tables_name.table_name|| ' for each row'|| ' declare '|| 'jobName varchar2(200);'|| 'tableName varchar2(200);'|| 'columnName varchar2(200);'|| 'str varchar2(2000);'|| 'pk_information varchar2(300);'|| ' begin '|| 'tableName := '''||tables_name.table_name||''';'; for primary_key_count in 1..var_array.count loop sql_str := sql_str|| 'pk_information := '''||var_array(primary_key_count)||'''||:new.'||var_array(primary_key_count)||';'; end loop; var_array.delete(); i:=0; sql_str := sql_str|| 'if updating then';
(4)拼接,判斷字段是否有變更,如若有記錄下來
-- get every column_name by table_name for columns_name in ( select t.table_name,t.column_name from user_tab_columns t where t.TABLE_NAME = tables_name.table_name ) loop -- the second set column to sql_str sql_str := sql_str|| ' if :new.'||columns_name.column_name||' <> :old.'||columns_name.column_name||' then'|| ' str := str||'''||columns_name.column_name||''';'|| 'end if;'; end loop; -- the third set the whole sql_str sql_str := sql_str|| ' insert into t_task ( JOB_NAME, TABLE_NAME, COLUMN_NAME , pk_information)'|| ' values ( ''update'', tableName, str, pk_information);'|| ' end if;'|| ' if inserting then'|| ' insert into t_task ( JOB_NAME, TABLE_NAME, COLUMN_NAME, pk_information)'|| ' values ( ''insert'', tableName, columnName, pk_information); '|| ' end if;'|| ' if deleting then'|| ' insert into t_task ( JOB_NAME, TABLE_NAME, COLUMN_NAME, pk_information)'|| ' values ( ''delete'', tableName, columnName, pk_information); '|| ' end if;'|| 'end task_for_link_'||table_name||';';
(5)執行腳本--when other then null(拋錯繼續執行)
begin execute immediate sql_str; exception when others then null; end; dbms_output.put_line(sql_str); end loop; end;