1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| 1)源端数据库必须允许DDL触发器的触发动作,即数据库参数_system_trig_enabled为TRUE或者未设置。查看该参数的命令如下: set line 200 col name for a25 col value for a30 col describ for a70 select x.ksppinm Name,y.ksppstvl Value,x.ksppdesc Describ from x$ksppi x,x$ksppcv y where x.inst_id=userenv('Instance') and y.inst_id=userenv('Instance') and x.indx=y.indx and x.ksppinm = '_system_trig_enabled'; 2)需要在源端数据库以sys用户,在PDB中的sys模式下创建DDL触发器及DDL记录表。 3)需要日志捕获模块对ddl_mask进行设置。例如<ddl_mask>op:obj<ddl_mask>。 --dmhs_ddl.sql脚本如下: CREATE TABLE DMHS_DDL_SQL ( OBJID NUMBER, DATAOBJ NUMBER, OP_TYPE VARCHAR2(32), OBJ_SCHNAME VARCHAR2(128), OBJ_NAME VARCHAR2(128), OBJ_TYPE VARCHAR2(32), OP_SQL VARCHAR(4000), OP_SQL2 CLOB, DDL_TIME DATE, RESVD1 NUMBER, RESVD2 NUMBER, RESVD3 NUMBER, RESVD4 NUMBER, RESVD5 VARCHAR2(1000), RESVD6 VARCHAR2(1000) );
create or replace trigger dmhs_trigger before ddl on database declare e1 exception; sql_text ora_name_list_t; ddl_sql clob; op_no number := NULL; objid number := NULL; dataobj number := NULL; v_num number; sql_item varchar(8000); sql_temp varchar(8000); begin
if (SUBSTR(ora_dict_obj_name, 1, 5) = 'DMHS_' and ora_dict_obj_name<>'DMHS_TRXID_TABLE') or (ora_dict_obj_owner = 'SYS' and ora_dict_obj_type != 'TABLESPACE') then if ora_dict_obj_name = 'DMHS_DDL_SQL' and ora_dict_obj_type = 'TABLE' and ora_sysevent = 'DROP' then raise_application_error(-20002, 'table cannot drop before dmhs_trigger is droped'); end if; if ora_sysevent != 'TRUNCATE' or ora_dict_obj_name <> 'DMHS_DDL_SQL' then return; end if; end if;
sql_temp := ''; dbms_lob.createtemporary(ddl_sql, TRUE); v_num := ora_sql_txt (sql_text); for i in 1 .. v_num loop sql_item := sql_text (i); if length(sql_item) + length(sql_temp) > 3000 then dbms_lob.append(ddl_sql, sql_temp); sql_temp := ''; end if; sql_temp := sql_temp || sql_item; end loop; dbms_lob.append(ddl_sql, sql_temp); if ora_sysevent != 'CREATE' then if ora_dict_obj_type = 'TABLE' or ora_dict_obj_type = 'SEQUENCE' then select o.obj#, o.dataobj# into objid, dataobj from sys.obj$ o, sys.user$ u where o.name = ora_dict_obj_name and o.type# in(2, 6) and o.subname is null and u.name = ora_dict_obj_owner and o.owner# = u.user#; end if; insert into dmhs_ddl_sql(objid, dataobj, op_type, obj_schname, obj_name, obj_type, op_sql, ddl_time) values(objid, dataobj, ora_sysevent, ora_dict_obj_owner, ora_dict_obj_name, ora_dict_obj_type, SUBSTR(ddl_sql, 1, 2000), sysdate); else if ora_dict_obj_type = 'TABLE' then insert into dmhs_ddl_sql(op_type, obj_schname, obj_name, obj_type, op_sql, op_sql2, ddl_time) values(ora_sysevent, ora_dict_obj_owner, ora_dict_obj_name, ora_dict_obj_type, SUBSTR(ddl_sql, 1, 2000), ddl_sql, sysdate); elsif ora_dict_obj_type in ('VIEW', 'MATERIALIZED VIEW', 'TRIGGER', 'PROCEDURE', 'FUNCTION', 'PACKAGE', 'PACKAGE BODY', 'TYPE', 'TYPE BODY', 'SYNONYM', 'TABLESPACE', 'USER', 'ROLE', 'INDEX', 'SEQUENCE') then insert into dmhs_ddl_sql(op_type, obj_schname, obj_name, obj_type, op_sql, op_sql2, ddl_time) values(ora_sysevent, ora_dict_obj_owner, ora_dict_obj_name, ora_dict_obj_type, SUBSTR(ddl_sql, 1, 2000), ddl_sql, sysdate); end if; end if; exception when e1 then raise e1; when no_data_found then dbms_output.put_line('object is not exist'); end dmhs_trigger; /
--SELECT * FROM SYS.USER_ERRORS A WHERE A.NAME = UPPER('DMHS_TRIGGER'); --1)关闭数据回收站 SHOW PARAMETER RECYCLE ALTER SYSTEM SET RECYCLEBIN=OFF DEFERRED; --授权 GRANT ALL ON SYS.DMHS_DDL_SQL TO DMHS; GRANT SELECT ANY TABLE TO DMHS; GRANT SELECT ANY DICTIONARY TO DMHS; GRANT CREATE SESSION TO DMHS; GRANT LOCK ANY TABLE TO DMHS; GRANT EXECUTE ON DBMS_FLASHBACK TO DMHS; GRANT FLASHBACK ANY TABLE TO DMHS;
|