Suppose I have an AFTER ALTER
trigger on my Oracle database and I rename some database object (ALTER ... RENAME TO ...
). Within the trigger, how do I determine the new name of the database object? It seems that the ORA_DICT_OBJ_OWNER
, ORA_DICT_OBJ_NAME
and ORA_DI开发者_C百科CT_OBJ_TYPE
functions all return the old values of the database object.
For example:
CREATE OR REPLACE TRIGGER ADAM_BEFORE_AFTER BEFORE ALTER ON DATABASE
BEGIN
DBMS_OUTPUT.put_line('Before alter: ' || ora_dict_obj_owner || '.' || ora_dict_obj_name || ' (' || ora_dict_obj_type || ')');
END;
CREATE OR REPLACE TRIGGER ADAM_AFTER_ALTER AFTER ALTER ON DATABASE
BEGIN
DBMS_OUTPUT.put_line('After alter: ' || ora_dict_obj_owner || '.' || ora_dict_obj_name || ' (' || ora_dict_obj_type || ')');
END;
Suppose I rename a table:
ALTER TABLE USELESS_TABLE9 RENAME TO USELESS_TABLE10
The database outputs this:
Before alter: DEVELOPER.USELESS_TABLE9 (TABLE) After alter: DEVELOPER.USELESS_TABLE9 (TABLE)
Update: Unfortunately, the output I presented above was incorrect. The output was actually being generated by a BEFORE DDL
trigger and an AFTER DDL
trigger I had created earlier, not by the BEFORE RENAME
and AFTER RENAME
triggers. I will continue to investigate why the BEFORE RENAME
and AFTER RENAME
triggers are not firing...
Update: It appears that the BEFORE RENAME
and AFTER RENAME
triggers refuse to fire, but the BEFORE ALTER
and AFTER ALTER
triggers do. I have updated the question accordingly.
ALTER RENAME
won't fire the trigger, RENAME x TO y
will.
As for your question about names before and after, I think you will have to parse the DDL to retrieve them, like that:
CREATE OR REPLACE TRIGGER MK_BEFORE_RENAME BEFORE RENAME ON SCHEMA
DECLARE
sql_text ora_name_list_t;
v_stmt VARCHAR2(2000);
n PLS_INTEGER;
BEGIN
n := ora_sql_txt(sql_text);
FOR i IN 1..n LOOP
v_stmt := v_stmt || sql_text(i);
END LOOP;
Dbms_Output.Put_Line( 'Before: ' || regexp_replace( v_stmt, 'rename[[:space:]]+([a-z0-9_]+)[[:space:]]+to.*', '\1', 1, 1, 'i' ) );
Dbms_Output.Put_Line( 'After: ' || regexp_replace( v_stmt, 'rename[[:space:]]+.*[[:space:]]+to[[:space:]]+([a-z0-9_]+)', '\1', 1, 1, 'i' ) );
END;
The regular expressions could surely be written more clearly, but it works:
RENAME
mktestx
TO mktesty;
Before: mktestx
After: mktesty
UPDATE To accommodate your changed question:
CREATE OR REPLACE TRIGGER MK_AFTER_ALTER AFTER ALTER ON SCHEMA
DECLARE
sql_text ora_name_list_t;
v_stmt VARCHAR2(2000);
n PLS_INTEGER;
BEGIN
n := ora_sql_txt(sql_text);
FOR i IN 1..n LOOP
v_stmt := v_stmt || sql_text(i);
END LOOP;
Dbms_Output.Put_Line( 'Before: ' || regexp_replace( v_stmt, 'alter[[:space:]]+table[[:space:]]+([a-z0-9_]+)[[:space:]]+rename[[:space:]]+to.*', '\1', 1, 1, 'i' ) );
Dbms_Output.Put_Line( 'After: ' || regexp_replace( v_stmt, 'alter[[:space:]]+table[[:space:]]+.*to[[:space:]]+([a-z0-9_]+)', '\1', 1, 1, 'i' ) );
END;
精彩评论