Oracle: как определить новое имя объекта в & # 8220; ПОСЛЕ ALTER & # 8221; спусковой крючок?
Вопрос
Предположим, у меня есть триггер AFTER ALTER
в моей базе данных Oracle, и я переименую некоторый объект базы данных ( ALTER ... RENAME TO ...
). Как определить новое имя объекта базы данных в триггере? Похоже, что функции ORA_DICT_OBJ_OWNER
, ORA_DICT_OBJ_NAME
и ORA_DICT_OBJ_TYPE
возвращают старые значения объекта базы данных.
Например:
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;
Предположим, я переименую таблицу:
ALTER TABLE USELESS_TABLE9 RENAME TO USELESS_TABLE10
База данных выводит это:
Before alter: DEVELOPER.USELESS_TABLE9 (TABLE) After alter: DEVELOPER.USELESS_TABLE9 (TABLE)
Обновление . К сожалению, приведенный выше вывод был неверным. Фактически выходные данные генерировались триггером BEFORE DDL
и триггером AFTER DDL
, которые я создал ранее, не с помощью BEFORE RENAME Триггеры
и AFTER RENAME
. Я продолжу исследовать, почему триггеры BEFORE RENAME
и AFTER RENAME
не срабатывают ...
Обновление . Похоже, что триггеры BEFORE RENAME
и AFTER RENAME
отказываются срабатывать, но BEFORE ALTER
и триггеры AFTER ALTER
делают. Я обновил вопрос соответственно.
Решение
ALTER RENAME
не сработает триггер, RENAME x TO y
.
Что касается вашего вопроса об именах до и после, я думаю, вам придется проанализировать DDL, чтобы получить их следующим образом:
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;
Регулярные выражения могут быть написаны более четко, но это работает:
RENAME
mktestx
TO mktesty;
Before: mktestx
After: mktesty
ОБНОВЛЕНИЕ Чтобы ответить на измененный вопрос:
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;