Oracle مجموعة PL/SQL المجمعة: مثال شامل

⚡ ملخص ذكي

خدمة التجميع بالجملة في Oracle تسترجع لغة PL/SQL العديد من الصفوف دفعة واحدة إلى مجموعة، بينما تقوم عبارة FORALL بإعادة تنفيذ عمليات DML بكميات كبيرة إلى قاعدة البيانات. يقلل كلا الأسلوبين من عمليات تبديل السياق بين محركي SQL وPL/SQL، مما يحسن الأداء.

  • 📦 خدمة التجميع بالجملة: يقوم بجلب عدة صفوف في تمريرة واحدة إلى متغير مجموعة، مما يحل محل عملية الجلب البطيئة صفًا تلو الآخر.
  • 🔁 للجميع: ينفذ عملية إدراج أو تحديث أو حذف واحدة عبر مجموعة كاملة باستخدام تبديل سياق واحد.
  • 📏 بند الحد: يحدد الحد الأقصى لعدد الصفوف التي يتم تحميلها في كل عملية جلب بيانات مجمعة (BULC COLLECT)، مما يحمي ذاكرة الجلسة على الجداول الكبيرة.
  • 📊 سمات التجميع بالجملة: تشير السمة %BULK_ROWCOUNT(n) إلى عدد الصفوف التي أثرت عليها عبارة FORALL DML رقم n.
  • ⚙️ المجموعات المطلوبة: يجب أن تستهدف عبارة INTO نوع مجموعة، مثل جدول متداخل أو مصفوفة ترابطية.
  • 🤖 مساعدة الذكاء الاصطناعي: تقوم المساعدات المدعومة بالذكاء الاصطناعي مثل GitHub Copilot بصياغة كتل BULK COLLECT و FORALL وتحديد بند LIMIT المفقود.

Oracle نظرة عامة على عبارات PL/SQL BULK COLLECT و FORALL مع عبارة LIMIT

ما هو الجمع بالجملة؟

يقلل التجميع المجمع من عمليات تبديل السياق بين SQL ومحرك PL/SQL ويسمح لمحرك SQL بجلب السجلات دفعة واحدة.

Oracle PL / SQL تُتيح هذه الخاصية جلب السجلات دفعةً واحدة بدلاً من جلبها واحدًا تلو الآخر. ويمكن استخدام BULK COLLECT في عبارة SELECT لتعبئة السجلات دفعةً واحدة، أو لجلبها بشكل فردي. المؤشر بشكل مجمع. بما أن BULK COLLECT يجلب السجلات دفعة واحدة، يجب أن تحتوي عبارة INTO دائمًا على متغير من نوع مجموعة. الميزة الرئيسية لاستخدام BULK COLLECT هي أنها تزيد الأداء عن طريق تقليل التفاعل بين قاعدة البيانات ومحرك PL/SQL.

بناء الجملة:

SELECT <column1> BULK COLLECT INTO bulk_variable FROM <table name>;
FETCH <cursor_name> BULK COLLECT INTO <bulk_variable>;

في الصيغة المذكورة أعلاه، يتم استخدام BULK COLLECT لجمع البيانات من عبارات SELECT و FETCH.

البند FORALL

تؤدي عبارة FORALL وظيفة عمليات DML تُعالج البيانات بكميات كبيرة. وهي تُشبه حلقة FOR، إلا أن العمليات في حلقة FOR تُنفذ على مستوى السجل، بينما لا يوجد مفهوم حلقة في FORALL. بدلاً من ذلك، تُعالج جميع البيانات الموجودة في النطاق المحدد في نفس الوقت.

بناء الجملة:

FORALL <loop_variable> in <lower range> .. <higher range>

<DML operations>;

في الصيغة المذكورة أعلاه، سيتم تنفيذ عملية DML المعطاة لجميع البيانات الموجودة بين النطاق الأدنى والنطاق الأعلى.

بند الحد

تعتمد تقنية التجميع المجمّع على تحميل جميع البيانات دفعةً واحدة إلى متغير المجموعة المستهدف، أي يتم ملء جميع البيانات في متغير المجموعة في عملية واحدة. إلا أن هذه التقنية غير مستحسنة عندما يكون إجمالي عدد السجلات المطلوب تحميلها كبيرًا جدًا، لأن محاولة PL/SQL تحميل جميع البيانات تستهلك قدرًا كبيرًا من ذاكرة الجلسة. لذا، يُنصح دائمًا بتقييد حجم عملية التجميع المجمّع هذه.

يمكن تحقيق حد الحجم هذا بسهولة عن طريق إدخال شرط ROWNUM في عبارة SELECT، بينما في حالة المؤشر، لا يكون ذلك ممكناً.

للتغلب على هذا ، Oracle وقد تم توفير بند LIMIT الذي يحدد عدد السجلات التي يجب تضمينها في المجموعة.

بناء الجملة:

FETCH <cursor_name> BULK COLLECT INTO <bulk_variable> LIMIT <size>;

في الصيغة المذكورة أعلاه، تستخدم عبارة جلب المؤشر عبارة BULK COLLECT مع عبارة LIMIT.

سمات التجميع المجمعة

على غرار خصائص المؤشر، تحتوي دالة BULK COLLECT على %BULK_ROWCOUNT(n) التي تُعيد عدد الصفوف المتأثرة في عبارة DML رقم n من عبارة FORALL، أي أنها تُعطي عدد السجلات المتأثرة في عبارة FORALL لكل قيمة من متغير المجموعة. يشير الرقم 'n' إلى تسلسل القيمة في المجموعة التي يلزم حساب عدد صفوفها.

مثال 1: في هذا المثال، سنقوم بعرض جميع أسماء الموظفين من جدول الموظفين باستخدام BULK COLLECT، وسنقوم أيضًا بزيادة رواتب جميع الموظفين بمقدار 5000 باستخدام FORALL.

تُظهر لقطة الشاشة أدناه مثال BULK COLLECT و FORALL هذا بالإضافة إلى مخرجاته في Oracle.

مثال على استخدام خياري "التجميع المجمع" و"الحد" و"الكل" لتحديث رواتب الموظفين في Oracle PL / SQL

DECLARE
CURSOR guru99_det IS SELECT emp_name FROM emp;
TYPE lv_emp_name_tbl IS TABLE OF VARCHAR2(50);
lv_emp_name lv_emp_name_tbl;
BEGIN
OPEN guru99_det;
FETCH guru99_det BULK COLLECT INTO lv_emp_name LIMIT 5000;
FOR c_emp_name IN lv_emp_name.FIRST .. lv_emp_name.LAST
LOOP
Dbms_output.put_line('Employee Fetched:'||c_emp_name);
END LOOP;
FORALL i IN lv_emp_name.FIRST .. lv_emp_name.LAST
UPDATE emp SET salary=salary+5000 WHERE emp_name=lv_emp_name(i);
COMMIT;
Dbms_output.put_line('Salary Updated');
CLOSE guru99_det;
END;
/

الناتج

Employee Fetched:BBB
Employee Fetched:XXX
Employee Fetched:YYY
Salary Updated

Code التفسير:

  • Code السطر 2: تعريف المؤشر guru99_det للعبارة 'SELECT emp_name FROM emp'.
  • Code السطر 3: تم تعريف lv_emp_name_tbl كنوع جدول من VARCHAR2(50).
  • Code السطر 4: تعريف lv_emp_name كنوع lv_emp_name_tbl.
  • Code السطر 6: فتح المؤشر.
  • Code السطر 7: جلب المؤشر باستخدام BULK COLLECT مع حجم LIMIT 5000 إلى متغير lv_emp_name.
  • Code الأسطر 8-11: إعداد حلقة FOR لطباعة جميع السجلات في المجموعة lv_emp_name.
  • Code السطر 12: استخدام FORALL لتحديث رواتب جميع الموظفين بمقدار 5000.
  • Code السطر 14: الالتزام بـ صفقة.

الأسئلة الشائعة

لا، لا يُصدر استعلام BULK COLLECT SELECT أي خطأ NO_DATA_FOUND؛ بل يُعيد مجموعة فارغة. اختبر المجموعة دائمًا باستخدام دالة .COUNT قبل البحث.pingوإلا فقد تقوم بمعالجة صفر صفوف بصمت.

تتيح عبارة SAVE EXCEPTIONS استمرار تنفيذ FORALL عند فشل صفوف فردية. يتم تخزين الصفوف الفاشلة في SQL%BULK_EXCEPTIONS، ثم Oracle يُثير ORA-24381، الذي تقوم باحتجازه في استثناء معالج لفحص كل خطأ.

استخدم BULK COLLECT عندما تقرأ حلقة تكرارية عدة صفوف. المؤشر تقوم حلقة FOR بجلب صف واحد لكل مفتاح، لذا فإن الجلب المجمع بالإضافة إلى FORALL يمكن أن يعمل بشكل أسرع عدة مرات على مجموعات النتائج الكبيرة.

تُعيد عملية BULK COLLECT عدة صفوف دفعة واحدة، لذا فهي تحتاج إلى حاوية متعددة الصفوف. يجب أن يكون هدف INTO مجموعة شتاء XNUMX مثل جدول متداخل، أو مصفوفة متغيرة، أو مصفوفة ترابطية، وليس متغيرًا عدديًا واحدًا.

لا. يُنفّذ رأس FORALL عملية إدراج أو تحديث أو حذف أو دمج واحدة فقط. القيم الموجودة في عبارات VALUES و WHERE هي فقط التي قد تتغير في كل تكرار. بالنسبة لعدة عبارات، استخدم عبارات FORALL منفصلة.

يمكن أن تكون المعالجة المجمعة أسرع بعدة مرات إلى أكثر من مائة مرة من التعليمات البرمجية صفًا تلو الآخر، لأن BULK COLLECT و FORALL يدمجان آلاف عمليات تبديل سياق المحرك في عدد قليل، مما يقلل بشكل حاد من الحمل الزائد على أحجام البيانات الكبيرة.

نعم. مساعد الطيار جيثب يقوم البرنامج باستخراج عمليات BULK COLLECT، وحلقات FORALL DML، وعبارات LIMIT من تعليق، ويقترح تعريفات لأنواع المجموعات، على الرغم من أنه يجب عليك مراجعة أحجام الدفعات ومعالجة الأخطاء بنفسك.

تقوم مساعدات الذكاء الاصطناعي بفحص الحلقات التي تجلب أو تغير صفًا واحدًا في كل مرة، وتوصي بإعادة كتابتها باستخدام BULK COLLECT وLIMIT وFORALL. يكشف هذا التقييم الآلي عن حدود LIMIT المفقودة ونقاط الضعف في الأداء قبل بدء الإنتاج.

تلخيص هذه التدوينة بـ: