2009-11-27 9 views
5

Supongamos que tengo un disparador AFTER ALTER en mi base de datos Oracle y cambio el nombre de un objeto de base de datos (ALTER ... RENAME TO ...). Dentro del disparador, ¿cómo determino el nuevo nombre del objeto de la base de datos? Parece que las funciones ORA_DICT_OBJ_OWNER, ORA_DICT_OBJ_NAME y ORA_DICT_OBJ_TYPE devuelven todos los valores antiguos del objeto de la base de datos.Oracle: ¿Cómo determino el NUEVO nombre de un objeto en un desencadenante "DESPUÉS DE ALTERAR"?

Por ejemplo:

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; 

Supongamos que cambiar el nombre de una tabla:

ALTER TABLE USELESS_TABLE9 RENAME TO USELESS_TABLE10 

Las salidas base de datos Este:

 
Before alter: DEVELOPER.USELESS_TABLE9 (TABLE) 
After alter: DEVELOPER.USELESS_TABLE9 (TABLE) 

Actualización: Por desgracia, la salida que presentó anteriormente era incorrecto. La salida en realidad estaba siendo generada por un activador BEFORE DDL y un activador AFTER DDL que había creado anteriormente, no por los activadores BEFORE RENAME y AFTER RENAME. Voy a seguir para investigar por qué los BEFORE RENAMEAFTER RENAME y disparadores no están disparando ...

Actualización: Parece que los BEFORE RENAMEAFTER RENAME y disparadores se niegan a disparar, pero los BEFORE ALTER y AFTER ALTER desencadenantes hacer. He actualizado la pregunta en consecuencia.

Respuesta

6

ALTER RENAME no disparará el gatillo, RENAME x TO y will.

cuanto a su pregunta acerca de los nombres antes y después, creo que tendrá que analizar el DDL para recuperarlos, así:

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; 

Las expresiones regulares sin duda se podrían escribir con más claridad, pero funciona :

RENAME 
mktestx 
TO     mktesty; 

Before: mktestx 
After: mktesty 

ACTUALIZACIÓN para acomodar su pregunta cambiado:

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; 
Cuestiones relacionadas