معالجة الاستثناءات في Oracle بل/SQL (أمثلة)
⚡ ملخص ذكي
معالجة الاستثناء في Oracle يلتقط PL/SQL أخطاء وقت التشغيل التي توقف تنفيذ كتلة، مما يسمح للمحرك بنقل التحكم إلى قسم الاستثناء حيث تستجيب المعالجات المحددة مسبقًا والمحددة من قبل المستخدم ومعالجات OTHERS أو تثير الأخطاء أو تنشرها بأمان.

ما هو التعامل مع الاستثناءات في PL/SQL؟
يحدث استثناء عندما يواجه محرك PL/SQL تعليمة لا يمكنه تنفيذها بسبب خطأ ينشأ أثناء التشغيل. لا يتم اكتشاف هذه الأخطاء أثناء الترجمة، وبالتالي يجب معالجتها فقط أثناء التشغيل.
على سبيل المثال، إذا تلقى محرك PL/SQL تعليمة لقسمة عدد على صفر، فإنه يُصدر خطأً كاستثناء. ويُصدر محرك PL/SQL هذا الاستثناء فقط أثناء التشغيل.
يؤدي حدوث استثناء إلى توقف البرنامج عن التنفيذ، لذا لتجنب هذه الحالة، يجب التقاط الخطأ ومعالجته بشكل منفصل. تُسمى هذه العملية بمعالجة الاستثناءات، حيث يتولى المبرمج معالجة الخطأ الذي قد يحدث أثناء التشغيل.
بناء جملة معالجة الاستثناءات
تُعالج الاستثناءات على مستوى الكتلة. بمجرد حدوث استثناء في كتلة ما، ينتقل التحكم من قسم التنفيذ في تلك الكتلة، ثم يُعالج الاستثناء في قسم معالجة الاستثناءات في الكتلة نفسها. بعد معالجة الاستثناء، لا يمكن للتحكم العودة إلى قسم التنفيذ في الكتلة ذاتها.
يوضح الرسم التوضيحي أدناه كيف يقع قسم التنفيذ وقسم معالجة الاستثناءات داخل كتلة PL/SQL واحدة:
يوضح التركيب النحوي أدناه كيفية التقاط ومعالجة الاستثناء.
BEGIN <execution block> . . EXCEPTION WHEN <exceptionl_name> THEN <Exception handling code for the “exception 1 _name’' > WHEN OTHERS THEN <Default exception handling code for all exceptions > END;
شرح بناء الجملة:
- في الصيغة أعلاه، تحتوي كتلة معالجة الاستثناءات على سلسلة من شروط WHEN لمعالجة الاستثناءات.
- يتبع كل شرط WHEN اسم استثناء من المتوقع أن يتم رفعه في وقت التشغيل.
- عندما يتم طرح استثناء في وقت التشغيل، يقوم محرك PL/SQL بالبحث في جزء معالجة الاستثناءات عن هذا الاستثناء المحدد، بدءًا من عبارة WHEN الأولى والتحرك بالتسلسل.
- إذا وجد معالجًا للاستثناء الذي تم طرحه، فإنه ينفذ رمز المعالج المحدد هذا.
- إذا لم تتطابق أي عبارة WHEN مع الاستثناء المُثار، يقوم محرك PL/SQL بتنفيذ جزء WHEN OTHERS، إن وُجد. هذا المعالج مشترك بين جميع الاستثناءات.
- بعد تشغيل المعالج، ينتقل التحكم من الكتلة الحالية.
- لا يمكن تنفيذ سوى معالج استثناء واحد لكل كتلة برمجية أثناء التشغيل. بعد تنفيذه، يتخطى المحرك معالجات الاستثناءات المتبقية ويغادر الكتلة البرمجية الحالية.
ملاحظة: يجب دائمًا وضع عبارة WHEN OTHERS في نهاية التسلسل. أي معالج مكتوب بعد WHEN OTHERS لا يتم تنفيذه أبدًا، لأن التحكم يخرج من الكتلة بمجرد تنفيذ WHEN OTHERS.
أنواع الاستثناء
يوجد نوعان من الاستثناءات في PL / SQL.
- الاستثناءات المحددة مسبقًا
- الاستثناءات المحددة من قبل المستخدم
الاستثناءات المحددة مسبقًا
Oracle يحتوي على بعض الاستثناءات الشائعة المُعرّفة مسبقًا. لكل استثناء مُعرّف مسبقًا اسم فريد ورقم خطأ، وجميعها مُعلنة في حزمة STANDARD في Oracleفي البرمجة، يمكنك استخدام أسماء الاستثناءات المُعرَّفة مسبقًا هذه مباشرةً لمعالجة الأخطاء المُقابلة. يرتبط العديد منها مباشرةً بأسماء شائعة. SQL أخطاء تواجهها كل يوم.
فيما يلي بعض الاستثناءات المحددة مسبقًا:
| استثناء | خطأ Code | سبب الاستثناء |
|---|---|---|
| ACCESS_INTO_NULL | ORA-06530 | إسناد قيمة لخصائص كائن غير مهيأ |
| الحالة_غير موجودة | ORA-06592 | لم يتم استيفاء أي من شروط WHEN في عبارة CASE، ولم يتم تحديد أي شرط ELSE. |
| COLLECTION_IS_NULL | ORA-06531 | استخدام أساليب التجميع (باستثناء EXISTS) أو الوصول إلى سمات المجموعة في مجموعة غير مهيأة |
| CURSOR_ALREADY_OPEN | ORA-06511 | محاولة فتح أ المؤشر هذا مفتوح بالفعل |
| DUP_VAL_ON_INDEX | ORA-00001 | تخزين قيمة مكررة في عمود قاعدة بيانات مقيد بفهرس فريد |
| INVALID_CURSOR | ORA-01001 | عمليات المؤشر غير القانونية، مثل إغلاق مؤشر غير مفتوح |
| رقم غير صالح | ORA-01722 | فشلت عملية تحويل الحرف إلى رقم بسبب وجود حرف رقمي غير صالح |
| لاتوجد بيانات | ORA-01403 | عبارة SELECT التي تحتوي على عبارة INTO لا تجلب أي صفوف |
| ROW_MISMATCH | ORA-06504 | نوع بيانات متغير المؤشر غير متوافق مع نوع الإرجاع الفعلي للمؤشر |
| SUBSCRIPT_BEYOND_COUNT | ORA-06533 | الإشارة إلى مجموعة برقم فهرس أكبر من حجم المجموعة |
| SUBSCRIPT_OUTSIDE_LIMIT | ORA-06532 | الإشارة إلى مجموعة برقم فهرس خارج النطاق القانوني (على سبيل المثال، -1) |
| TOO_MANY_ROWS | ORA-01422 | عبارة SELECT التي تحتوي على عبارة INTO تُرجع أكثر من صف واحد |
| VALUE_ERROR | ORA-06502 | خطأ حسابي أو خطأ في قيود الحجم (على سبيل المثال، تعيين قيمة أكبر من حجم المتغير) |
| ZERO_DIVIDE | ORA-01476 | قسمة عدد على صفر |
استثناء محدد من قبل المستخدم
إلى جانب الاستثناءات المُعرَّفة مسبقًا المذكورة أعلاه، يُمكن للمبرمج إنشاء استثناءات مُخصصة ومعالجتها. تُنشأ هذه الاستثناءات على مستوى البرنامج الفرعي في قسم التصريح، وتكون مرئية فقط داخل ذلك البرنامج الفرعي. أما الاستثناء المُعرَّف في مواصفات الحزمة فهو استثناء عام، ويكون مرئيًا في أي مكان يُمكن الوصول فيه إلى الحزمة.
بناء الجملة: على مستوى البرنامج الفرعي
DECLARE <exception_name> EXCEPTION; BEGIN <Execution block> EXCEPTION WHEN <exception_name> THEN <Handler> END;
- في الصيغة أعلاه، تم تعريف المتغير 'exception_name' على أنه نوع الاستثناء.
- ويمكن استخدامه بعد ذلك بنفس طريقة الاستثناء المحدد مسبقًا.
بناء الجملة: على مستوى مواصفات الحزمة
CREATE PACKAGE <package_name> IS <exception_name> EXCEPTION; . . END <package_name>;
- في الصيغة أعلاه، تم تعريف المتغير 'exception_name' على أنه نوع الاستثناء في مواصفات الحزمة لـ .
- يمكن استخدامه في جميع أنحاء قاعدة البيانات أينما يمكن استدعاء الحزمة 'package_name'.
استثناء رفع PL/SQL
تُثار جميع الاستثناءات المُعرَّفة مسبقًا ضمنيًا عند حدوث الخطأ المُناسب. أما الاستثناءات التي يُعرِّفها المستخدم، فيجب إثارتها صراحةً باستخدام الكلمة المفتاحية RAISE. يُمكن استخدام RAISE بالطرق الموضحة أدناه.
إذا استُخدمت الدالة RAISE بمفردها داخل معالج الاستثناءات، فإنها تنقل الاستثناء الذي تم رفعه مسبقًا إلى الكتلة الأصلية. ولا يمكن استخدامها إلا داخل كتلة استثناءات، كما هو موضح أدناه.
تُظهر لقطة الشاشة أدناه استخدام RAISE بمفرده لإعادة رفع استثناء إلى الكتلة المحيطة:
CREATE [ PROCEDURE | FUNCTION ] AS BEGIN <Execution block> EXCEPTION WHEN <exception_name> THEN <Handler> RAISE; END;
شرح بناء الجملة:
- في الصيغة أعلاه، يتم استخدام الكلمة المفتاحية RAISE داخل كتلة معالجة الاستثناءات.
- عندما يواجه البرنامج الاستثناء 'exception_name'، يتم التعامل مع الاستثناء ويكتمل بشكل طبيعي.
- ثم تقوم الكلمة المفتاحية RAISE في المعالج بنشر نفس الاستثناء إلى البرنامج الأصل.
ملاحظة: عند إثارة استثناء في الكتلة الأصلية، يجب أن يكون الاستثناء الذي يتم إثارته مرئيًا أيضًا في الكتلة الأصلية؛ وإلا Oracle يلقي خطأ.
يمكنك أيضًا استخدام الكلمة المفتاحية RAISE متبوعةً باسم الاستثناء لإطلاق استثناء مُعرَّف من قِبل المستخدم أو مُعرَّف مسبقًا. يُمكن استخدام هذه الصيغة في كلٍّ من جزء التنفيذ وجزء معالجة الاستثناءات.
تُظهر لقطة الشاشة أدناه الأمر RAISE متبوعًا باسم الاستثناء لرفع استثناء معين:
CREATE [ PROCEDURE | FUNCTION ] AS BEGIN <Execution block> RAISE <exception_name> EXCEPTION WHEN <exception_name> THEN <Handler> END;
شرح بناء الجملة:
- في الصيغة أعلاه، يتم استخدام الكلمة المفتاحية RAISE في جزء التنفيذ، متبوعة بالاستثناء 'exception_name'.
- يؤدي هذا إلى ظهور هذا الاستثناء المحدد في وقت التشغيل، ثم يجب معالجته أو إثارته بشكل أكبر.
مثال 1: في هذا المثال، سنرى:
- كيفية إعلان استثناء
- كيفية إثارة الاستثناء المُعلن
- كيفية نشره إلى الكتلة الرئيسية
تُظهر لقطة الشاشة أدناه الكتلة الكاملة التي تُعلن عن sample_exception، وتُثيرها داخل كتلة متداخلة، وتُمررها إلى الكتلة الرئيسية:
تُظهر لقطة الشاشة التالية نفس المثال مُكملاً، حيث تلتقط الكتلة الرئيسية في النهاية الاستثناء المُنتشر:
DECLARE Sample_exception EXCEPTION; PROCEDURE nested_block IS BEGIN Dbms_output.put_line('Inside nested block'); Dbms_output.put_line('Raising sample_exception from nested block'); RAISE sample_exception; EXCEPTION WHEN sample_exception THEN Dbms_output.put_line ('Exception captured in nested block. Raising to main block'); RAISE; END; BEGIN Dbms_output.put_line('Inside main block'); Dbms_output.put_line('Calling nested block'); Nested_block; EXCEPTION WHEN sample_exception THEN Dbms_output.put_line ('Exception captured in main block'); END; /
Code التفسير:
- Code السطر 2: تعريف المتغير 'sample_exception' كنوع استثناء.
- Code السطر 3: إعلان الإجراء nested_block.
- Code السطر 6: طباعة العبارة "داخل كتلة متداخلة".
- Code السطر 7: طباعة العبارة "رفع استثناء sample_exception من كتلة متداخلة".
- Code السطر 8: رفع الاستثناء باستخدام "RAISE Sample_exception".
- Code السطر 10: معالج الاستثناء الخاص بالاستثناء sample_exception في الكتلة المتداخلة.
- Code السطر 11: طباعة العبارة "تم التقاط استثناء في كتلة متداخلة. جارٍ رفعه إلى الكتلة الرئيسية".
- Code السطر 12: رفع الاستثناء إلى الكتلة الرئيسية (نشره).
- Code السطر 15: طباعة العبارة "داخل الكتلة الرئيسية".
- Code السطر 16: طباعة العبارة "استدعاء الكتلة المتداخلة".
- Code السطر 17: استدعاء إجراء nested_block.
- Code السطر 19: معالج الاستثناء لـ Sample_exception في الكتلة الرئيسية.
- Code السطر 20: طباعة العبارة "تم التقاط الاستثناء في الكتلة الرئيسية".
نقاط مهمة يجب ملاحظتها في الاستثناء
- في الدالة، يجب أن يُعيد الاستثناء قيمةً أو أن يُثير الاستثناء بشكلٍ أكبر؛ وإلا Oracle يُصدر خطأ "تم إرجاع الدالة بدون قيمة" أثناء التشغيل.
- بيانات التحكم في المعاملات يمكن إصدارها داخل كتلة معالجة الاستثناءات.
- SQLERRM و SQLCODE هما دالتان مدمجتان تقومان بإرجاع رسالة الاستثناء ورمز الاستثناء على التوالي.
- إذا لم يتم التعامل مع الاستثناء، فسيتم التراجع عن جميع المعاملات النشطة في تلك الجلسة بشكل افتراضي.
- RAISE_APPLICATION_ERROR (- ، يمكن استخدام ) بدلاً من RAISE لإظهار خطأ برمز ورسالة مخصصين. يجب أن يكون رمز الخطأ بين -20000 و-20999.





