Oracle: ¿Cómo puedo determinar el NUEVO nombre de un objeto en un activador “DESPUÉS DE ALTERAR”?

StackOverflow https://stackoverflow.com/questions/1809787

  •  05-07-2019
  •  | 
  •  

Pregunta

Supongamos que tengo un desencadenador AFTER ALTER en mi base de datos Oracle y cambio el nombre de algún objeto de base de datos ( ALTER ... RENAME TO ... ). Dentro del activador, ¿cómo puedo determinar el nombre nuevo 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 los valores old del objeto de la base de datos.

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 cambio el nombre de una tabla:

ALTER TABLE USELESS_TABLE9 RENAME TO USELESS_TABLE10

La base de datos produce esto:

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

Actualización: Desafortunadamente, la salida que presenté anteriormente era incorrecta. La salida en realidad fue generada por un desencadenador BEFORE DDL y un desencadenador AFTER DDL que había creado anteriormente, no por el ANTES DE NOMBRARSE y AFTER RENAME se activan. Continuaré investigando por qué los disparadores ANTES DE NOMBRAR y DESPUÉS DE RENOMBRAR no se activan ...

Actualización: Parece que los disparos ANTES DE NOMBRAR y AFTER RENAME se niegan a disparar, pero el ANTES DE ALTERAR EL y DESPUÉS DE ALTERAR los disparadores hacen. He actualizado la pregunta en consecuencia.

¿Fue útil?

Solución

ALTER RENAME no disparará el disparador, RENAME x TO y lo hará.

En cuanto a su pregunta sobre 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 seguramente podrían escribirse más claramente, pero funciona:

RENAME 
mktestx
TO                 mktesty;

Before: mktestx
After: mktesty

ACTUALIZACIÓN Para adaptarse a su pregunta modificada:

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;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top