سؤال

هذه هي حالة الاستخدام الخاصة بي:الإدخال عبارة عن سلسلة تمثل بيان أوراكل PL/SQL من التعقيد التعسفي.قد نفترض أنها عبارة واحدة (وليست نصًا).الآن، عدة يجب إعادة كتابة البتات من سلسلة الإدخال هذه.

على سبيل المثاليجب أن تكون أسماء الجداول مسبوقة، ويجب تعيين الوظائف المجمعة في قائمة التحديد التي لا تستخدم اسمًا مستعارًا للعمود كوظيفة افتراضية:

SELECT SUM(ABS(x.value)), 
TO_CHAR(y.ID,'111,111'),
y.some_col
FROM
tableX x,
(SELECT DISTINCT ID
FROM tableZ z
WHERE ID > 10) y
WHERE
...

يصبح

SELECT SUM(ABS(x.value)) COL1, 
TO_CHAR(y.ID,'111,111') COL2,
y.some_col
FROM
pref.tableX x,
(SELECT DISTINCT ID, some_col
FROM pref.tableZ z
WHERE ID > 10) y
WHERE
...

(تنصل:فقط لتوضيح المشكلة، البيان ليس له معنى)

نظرًا لأن الوظائف المجمعة قد تكون متداخلة وأن التحديدات الفرعية عبارة عن b_tch، فلا أجرؤ على استخدام التعبيرات العادية.حسنًا، في الواقع لقد نجحت وحققت 80% من النجاح، لكني بحاجة إلى الـ 20% المتبقية.

أفترض أن النهج الصحيح هو استخدام القواعد النحوية والمحللين.لقد عبثت بـ c++ ANTLR2 (على الرغم من أنني لا أعرف الكثير عن القواعد النحوية والتحليل بمساعدة ذلك).لا أرى طريقة سهلة للحصول على بتات SQL:

list<string> *ssel = theAST.getSubSelectList(); // fantasy land

هل يمكن لأي شخص أن يقدم بعض المؤشرات حول كيفية متابعة "محترفي التحليل" لهذه المشكلة؟يحرر:انا استخدم أوراكل 9i.

هل كانت مفيدة؟

المحلول

ربما يمكنك استخدام هذا، فهو يغير عبارة التحديد إلى كتلة XML:

declare
    cl clob;
begin
    dbms_lob.createtemporary (
        cl,
        true
    );
    sys.utl_xml.parsequery (
        user,
        'select e.deptno from emp e where deptno = 10',
        cl
    );
    dbms_output.put_line (cl);
    dbms_lob.freetemporary (cl);
end;
/ 

<QUERY>
  <SELECT>
    <SELECT_LIST>
      <SELECT_LIST_ITEM>
        <COLUMN_REF>
          <SCHEMA>MICHAEL</SCHEMA>
          <TABLE>EMP</TABLE>
          <TABLE_ALIAS>E</TABLE_ALIAS>
          <COLUMN_ALIAS>DEPTNO</COLUMN_ALIAS>
          <COLUMN>DEPTNO</COLUMN>
        </COLUMN_REF>
        ....
        ....
        ....
</QUERY>

انظر هنا: http://forums.Oracle.com/forums/thread.jspa?messageID=3693276&#3693276

الآن أنت "فقط" بحاجة إلى تحليل كتلة XML هذه.

تحرير 1:

للأسف لا أفهم تمامًا احتياجات OP ولكني آمل أن يكون هذا مفيدًا (إنها طريقة أخرى لطرح "أسماء" أعمدة الاستعلام على سبيل المثال select count(*),max(dummy) from dual):

set serveroutput on

DECLARE
 c       NUMBER;
 d       NUMBER;
 col_cnt PLS_INTEGER;
 f       BOOLEAN;
 rec_tab dbms_sql.desc_tab;
 col_num NUMBER;

PROCEDURE print_rec(rec in dbms_sql.desc_rec) IS
BEGIN
  dbms_output.new_line;
  dbms_output.put_line('col_type = ' || rec.col_type);
  dbms_output.put_line('col_maxlen = ' || rec.col_max_len);
  dbms_output.put_line('col_name = ' || rec.col_name);
  dbms_output.put_line('col_name_len = ' || rec.col_name_len);
  dbms_output.put_line('col_schema_name= ' || rec.col_schema_name);
  dbms_output.put_line('col_schema_name_len= ' || rec.col_schema_name_len);
  dbms_output.put_line('col_precision = ' || rec.col_precision);
  dbms_output.put_line('col_scale = ' || rec.col_scale);
  dbms_output.put('col_null_ok = ');

  IF (rec.col_null_ok) THEN
    dbms_output.put_line('True');
  ELSE
    dbms_output.put_line('False');
  END IF;
END;

BEGIN
  c := dbms_sql.open_cursor; 
  dbms_sql.parse(c,'select count(*),max(dummy) from dual ',dbms_sql.NATIVE); 
  dbms_sql.describe_columns(c, col_cnt, rec_tab);

  for i in rec_tab.first..rec_tab.last loop
    print_rec(rec_tab(i));
  end loop;

  dbms_sql.close_cursor(c);
END;
/

(انظر هنا لمزيد من المعلومات: http://www.psoug.org/reference/dbms_sql.html)

يريد OP أيضًا أن يكون قادرًا على تغيير اسم مخطط الجدول في الاستعلام.أعتقد أن أسهل طريقة لتحقيق ذلك هي الاستعلام عن أسماء الجداول منها user_tables وابحث في عبارة SQL عن أسماء الجداول هذه وقم بوضع بادئة لها أو للقيام بذلك 'alter session set current_schema = ....'.

نصائح أخرى

إذا كان مصدر سلاسل عبارات SQL هو مبرمجون آخرون، فيمكنك ببساطة الإصرار على أن الأجزاء التي تحتاج إلى التغيير يتم تمييزها ببساطة بواسطة اصطلاحات هروب خاصة، على سبيل المثال، اكتب $TABLE بدلاً من اسم الجدول، أو $TABLEPREFIX حيث يلزم وجود واحد.ومن ثم يمكن العثور على الأماكن التي تحتاج إلى التصحيح من خلال البحث عن سلسلة فرعية واستبدالها.

إذا كان لديك بالفعل سلاسل SQL عشوائية ولا يمكنك تمييزها بشكل جيد، فستحتاج إلى تحليل سلسلة SQL بطريقة ما كما لاحظت.من المؤكد أن حل XML هو إحدى الطرق الممكنة.

هناك طريقة أخرى وهي استخدام أ نظام تحويل البرنامج.يمكن لمثل هذه الأداة تحليل سلسلة لمثيل لغة، وإنشاء ASTs، وتنفيذ التحليل والتحويل على ASTs، ثم نشر سلسلة منقحة.

ال مجموعة أدوات إعادة هندسة برمجيات DMS هو مثل هذا النظام.يحتوي على محلل الواجهة الأمامية PLSQL.ويمكنه استخدام التحويلات الموجهة نحو النمط لإنجاز عمليات إعادة الكتابة التي يبدو أنك بحاجة إليها.على سبيل المثال الخاص بك الذي يتضمن عناصر محددة:

domain PLSQL.
rule use_explicit_column(e: expression):select_item -> select_item
   "\e" -> "\e \column\(\e\)".

لقراءة القاعدة، عليك أن تفهم أن الأشياء الموجودة داخل علامات الاقتباس تمثل أشجارًا مجردة في بعض لغات الكمبيوتر التي نريد معالجتها.ما تقوله عبارة "مجال PLSQL" هو "استخدم محلل PLSQL" لمعالجة محتوى السلسلة المقتبسة، وهذه هي الطريقة التي يعرفها.(يحتوي DMS على الكثير من محللي اللغة للاختيار من بينها).راجع مخططات السكك الحديدية في دليل PLSQL المرجعي الخاص بك.تمثل الشرطة المائلة العكسية معلومات الهروب/الوصف بدلاً من بناء جملة اللغة المستهدفة.

ما تقوله القاعدة هو تحويل تلك العناصر التي تم تحليلها حدد_العنصرs that are composed solely of an تعبير , وذلك بتحويله إلى حدد_العنصر تتكون من نفس التعبير والعمود المقابل ( \عمود(\ه) ) من المفترض أن يعتمد على الموضع في قائمة العناصر المحددة لجدول محدد.سيكون عليك تنفيذ أ عمود وظيفة يمكنها تحديد الاسم المقابل من موضع العنصر المحدد.في هذا المثال، اخترت تعريف دالة العمود لقبول التعبير عن الاهتمام كوسيطة؛يتم تمرير التعبير فعليًا باعتباره الشجرة المطابقة، وبالتالي يمكن لوظيفة العمود تحديد مكان وجوده في اختيار العناصر list من خلال السير على شجرة بناء الجملة المجردة.

تتعامل هذه القاعدة مع العناصر المحددة فقط.يمكنك إضافة المزيد من القواعد للتعامل مع الحالات المتنوعة الأخرى التي تهمك.

ما يفعله نظام التحويل لك هو:

  • تحليل جزء اللغة من الفائدة
  • بناء AST
  • let you pattern match for places of interest (by doing AST pattern matching) but using the surface syntax of the target langauge
  • استبدال الأنماط المتطابقة بأنماط أخرى
  • حساب البدائل الشريانية (مثل ASTs)
  • إعادة إنشاء النص المصدر من ASTs المعدلة.

While writing the rules isn't always trivial, it is what is necessary if your problem is stated as posed.

يعد حل XML المقترح طريقة أخرى لإنشاء مثل هذه AST.لا يحتوي على خصائص مطابقة الأنماط الرائعة على الرغم من أنك قد تتمكن من الاستفادة كثيرًا من XSLT.ما لا أعرفه هو ما إذا كان ملف XML يحتوي على شجرة التحليل بالتفصيل الكامل؛يوفر محلل DMS هذا حسب التصميم لأنه ضروري إذا كنت تريد إجراء تحليل وتحويل عشوائي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top