触发器如下,功能就是把更改对象的DDL语句保存到表里(包括DROP).
CREATE OR REPLACE TRIGGER TRI_ALTE_OBJECT
AFTER DDL ON database
--将DROP掉的对象创建语句保存到文件
declare
v_owner varchar2(50);
V_SOURCE CLOB;
I INTEGER;
BEGIN
DBMS_OUTPUT.put_line(ORA_SYSEVENT);
IF UPPER(ORA_SYSEVENT) = 'ALTER' AND UPPER(ORA_SYSEVENT) <> 'DROP' THEN--防止重复执行触发器,DROP好像也属于ALTER。
DBMS_OUTPUT.put_line(ora_dict_obj_type);
DBMS_OUTPUT.put_line(ora_dict_obj_name);
DBMS_OUTPUT.put_line(ora_dict_obj_owner);
SELECT dbms_metadata.get_ddl(ora_dict_obj_type,
ora_dict_obj_name,
ora_dict_obj_owner)
INTO V_SOURCE
FROM dual;
insert into VERSION_CONTROL
values
(ora_dict_obj_owner, ORA_LOGIN_USER, SYSDATE, V_SOURCE);
end if;
end;
/
但是发现了一个问题,由于是AFTER 触发器,我删除一个表的时候,如果该表上有索引的话,会出现错误,错误信息如下:
--这里我删除的是测试表hehe
14:05:47 SCOTT@orcl> drop table hehe;
ALTER
TABLE
HEHE
SCOTT
ALTER
INDEX
SYS_C0012714
SCOTT
drop table hehe
*
第 1 行出现错误:
ORA-00604: 递归 SQL 级别 2 出现错误
ORA-31603: 对象 "SYS_C0012714" 属于类型 INDEX, 在方案 "SCOTT" 中未找到
ORA-06512: 在 "SYS.DBMS_SYS_ERROR", line 105
ORA-06512: 在 "SYS.DBMS_METADATA", line 3912
ORA-06512: 在 "SYS.DBMS_METADATA", line 5678
ORA-06512: 在 line 1
ORA-06512: 在 line 28
据我分析,应该是删除了表,所以表上的索引已经没有了,所以找不到.
然后我又改为了前置触发器(BEFORE),执行删除,这会没报错,但是根据打印出的信息又发现一个问题:
14:06:41 SCOTT@orcl> drop table hehe;
DROP
ALTER
TABLE
HEHE
SCOTT
ALTER
INDEX
SYS_C0012714
SCOTT
ALTER
TABLE
HEHE
SCOTT
表已删除。
--可以看到开始执行的操作是DROP,后面又是ALTER表HEHE,然后是ALTER表上的索引SYS_C0012714(这里我成功保存了索引的创建信息),但是最后又出来一个ALTER表HEHE,这样我就重复记录了一次表HEHE的创建信息.
请问大神有没有研究过这个的,指导一下吧?