أوراكل: كيف يمكنني تحديد الاسم الجديد لكائن في مشغل "بعد تغيير"؟

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

  •  05-07-2019
  •  | 
  •  

سؤال

لنفترض أن لدي 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;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top