Oracle:“ AFTER ALTER”内のオブジェクトの新しい名前を確認する方法引き金?
質問
Oracleデータベースに AFTER ALTER
トリガーがあり、データベースオブジェクトの名前を変更するとします( ALTER ... RENAME TO ...
)。トリガー内で、データベースオブジェクトの新しい名前を確認するにはどうすればよいですか? ORA_DICT_OBJ_OWNER
、 ORA_DICT_OBJ_NAME
および ORA_DICT_OBJ_TYPE
関数はすべて、データベースオブジェクトの old 値を返すようです。
例:
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;
所属していません StackOverflow