Oracle: comment déterminer le NOUVEAU nom d'un objet dans un fichier & # 8220; AFTER ALTER & # 8221; déclencheur?
Question
Supposons que j'ai un déclencheur AFTER ALTER
sur ma base de données Oracle et que je renomme un objet de base de données ( ALTER ... RENAME TO ...
). Dans le déclencheur, comment puis-je déterminer le nouveau nom de l'objet de base de données? Il semble que les fonctions ORA_DICT_OBJ_OWNER
, ORA_DICT_OBJ_NAME
et ORA_DICT_OBJ_TYPE
renvoient toutes les valeurs anciennes de l'objet de base de données.
Par exemple:
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;
Supposons que je renomme une table:
ALTER TABLE USELESS_TABLE9 RENAME TO USELESS_TABLE10
La base de données génère ceci:
Before alter: DEVELOPER.USELESS_TABLE9 (TABLE) After alter: DEVELOPER.USELESS_TABLE9 (TABLE)
Mise à jour: Malheureusement, le résultat présenté ci-dessus était incorrect. La sortie était en fait générée par un déclencheur BEFORE DDL
et un déclencheur AFTER DDL
que j'avais créé précédemment, pas par le BEFORE RENAME
et les déclencheurs AFTER RENAME
. Je continuerai à rechercher pourquoi les déclencheurs BEFORE RENAME
et AFTER RENAME
ne se déclenchent pas ...
Mise à jour: Il semble que les déclencheurs BEFORE RENAME
et AFTER RENAME
refusent de se déclencher, mais le BEFORE ALTER
et les déclencheurs AFTER ALTER
le font. J'ai mis à jour la question en conséquence.
La solution
ALTER RENAME
ne déclenchera pas le déclencheur, RENAME x TO y
le fera.
En ce qui concerne votre question sur les noms avant et après, je pense que vous devrez analyser le DDL pour les récupérer, comme suit:
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;
Les expressions régulières pourraient certainement être écrites plus clairement, mais cela fonctionne:
RENAME
mktestx
TO mktesty;
Before: mktestx
After: mktesty
METTRE À JOUR pour répondre à la question modifiée:
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;