Oracle: come posso determinare il NUOVO nome di un oggetto in un & # 8220; AFTER ALTER & # 8221; grilletto?

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

  •  05-07-2019
  •  | 
  •  

Domanda

Supponiamo di avere un trigger AFTER ALTER sul mio database Oracle e di rinominare alcuni oggetti del database ( ALTER ... RENAME TO ... ). All'interno del trigger, come posso determinare il nuovo nome dell'oggetto database? Sembra che le funzioni ORA_DICT_OBJ_OWNER , ORA_DICT_OBJ_NAME e ORA_DICT_OBJ_TYPE restituiscono tutti i valori vecchi dell'oggetto database.

Ad esempio:

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;

Supponiamo di rinominare una tabella:

ALTER TABLE USELESS_TABLE9 RENAME TO USELESS_TABLE10

Il database genera questo:

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

Aggiornamento: Sfortunatamente, l'output che ho presentato sopra non era corretto. L'output era in realtà generato da un trigger PRIMA del DDL e da un trigger AFTER DDL che avevo creato in precedenza, non dal PRIMA DEL RENAME e AFTER RENAME vengono attivati. Continuerò a indagare sul perché i trigger PRIMA DEL RENAME e AFTER RENAME non si attivano ...

Aggiornamento: sembra che il PRIMA DEL RINAME e il AFTER RENAME inneschino il rifiuto del fuoco, ma il PRIMA DI ALTER e DOPO ALTER attivano. Ho aggiornato la domanda di conseguenza.

È stato utile?

Soluzione

ALTER RENAME non attiva il trigger, RENAME x TO y lo farà.

Per quanto riguarda la tua domanda sui nomi prima e dopo, penso che dovrai analizzare il DDL per recuperarli, in questo modo:

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;

Le espressioni regolari potrebbero sicuramente essere scritte più chiaramente, ma funziona:

RENAME 
mktestx
TO                 mktesty;

Before: mktestx
After: mktesty

AGGIORNAMENTO Per soddisfare la tua domanda modificata:

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;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top