أوراكل: كيف يمكنني تحديد الاسم الجديد لكائن في مشغل "بعد تغيير"؟
سؤال
لنفترض أن لدي 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;