Oracle: como determino o novo nome de um objeto em um gatilho "após alter"?
Pergunta
Suponha que eu tenho um AFTER ALTER
Trigger no meu banco de dados Oracle e renomei algum objeto de banco de dados (ALTER ... RENAME TO ...
). Dentro do gatilho, como faço para determinar o novo Nome do objeto de banco de dados? Parece que o ORA_DICT_OBJ_OWNER
, ORA_DICT_OBJ_NAME
e ORA_DICT_OBJ_TYPE
Funções retornam o velho valores do objeto de banco de dados.
Por exemplo:
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;
Suponha que eu renomeei uma tabela:
ALTER TABLE USELESS_TABLE9 RENAME TO USELESS_TABLE10
O banco de dados gera isto:
Before alter: DEVELOPER.USELESS_TABLE9 (TABLE) After alter: DEVELOPER.USELESS_TABLE9 (TABLE)
Atualizar: Infelizmente, a saída que apresentei acima estava incorreta. A saída estava realmente sendo gerada por um BEFORE DDL
gatilho e um AFTER DDL
gatilho que eu havia criado anteriormente, não pelo BEFORE RENAME
e AFTER RENAME
gatilhos. Vou continuar investigando por que o BEFORE RENAME
e AFTER RENAME
Os gatilhos não estão disparando ...
Atualizar: Parece que o BEFORE RENAME
e AFTER RENAME
gatilhos se recusam a disparar, mas o BEFORE ALTER
e AFTER ALTER
gatilhos fazem. Eu atualizei a pergunta de acordo.
Solução
ALTER RENAME
não vai disparar o gatilho, RENAME x TO y
vai.
Quanto à sua pergunta sobre nomes antes e depois, acho que você terá que analisar o DDL para recuperá -los, assim:
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;
As expressões regulares certamente podem ser escritas com mais clareza, mas funciona:
RENAME
mktestx
TO mktesty;
Before: mktestx
After: mktesty
ATUALIZAR Para acomodar sua pergunta alterada:
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;