الانتقال إلى المحتوى

من مزايا أوراكل 10g الحزمة Dml Error Logging


sky information

Recommended Posts

DML Error Logging




هل حاولت مرة أن تحدث مجموعة كبيرة من السجلات وبعض عدة ثواني تفشل المحاولة بسب سجل واحد تعارض مع القيد, أو هل أدخلت سجلات عن طريق عبارة
insert-as-select ثم تفشل المحاولة في إدخال فرضا 999 سجل من 1000 سجل بسب إدخال قيمة كبيرة في عمود ما ؟؟؟ لكن باستخدام DML error logging و بإضافة عبارة واحدة إلى عبارة Select سوف تسبب نجاح إدخال الـ999 سجل والسجل المسبب للخطأ سوف يسجل خارجا في جدول

لنبدأ :

نعمل جدول يحوي مع بعض القيود لغرض الانتهاك(انتهاك القيد الفريد):

SQL> create table dmlel 
(pkey varchar2(100) primary key,
field1 varchar2(1), 
field2  varchar2(10) not null);



الآن لنعمل سكربت يفشل بدون استخدام DML error logging
, السكربت التالي سيقوم إدخال بعض الصفوف وبعد ذلك سوف يفشل بسبب قيمة كبيرة للعمود:

Declare
i number;
Begin
i := 0;
while i <= 10 loop
insert into dmlel (pkey, field1, field2)
values (i, i, i);
i := i+1;
end loop;
End;
/
*
[color=#990000]ERROR at line 1:
ORA-12899: value too large for column "BULKLOAD"."DMLEL"."FIELD1" (actual: 2, maximum: 1)
ORA-06512: at line 5[/color]



من الملاحظ أن القيمة كبيرة جدا على العمود FIELD1 لأن عدد الخانات المحددة له هي خانة واحدة وحين تصل حلقة الدوران إلى العدد 10 سيكون قيمة i=10 وهي أكبر من القيمة المحددة للعمود ولذلك حصل الخطأ الذي أدى إلى فشل إدخال جميع السجلات .
لكي نعالج هذا الخطأ باستخدام DML error logging يجب أولا إنشاء جدول لأخطاء DML لكي تسجل فيه.

إنشاء Error Logging Table:

هنالك طريقتان لإنشاء هذا الجدول الطريقة الأولى بشكل آلي أما الثانية بشكل يدوي ,سوف نتكلم عن الطريقة الآلية فقط إن الأوراكل يوفر built-in pl/sql package تسمى DBMS_ERRLOG وهي خصوصا لهذا الغرض.

SQL> begin
dbms_errlog.create_error_log('DMLEL','ERROR_LOG_DMLEL');
 end;
/

PL/SQL procedure successfully completed.

SQL> desc error_log_dmlel
Name									  Null?	Type
----------------------------------------- -------- ----------------------------
ORA_ERR_NUMBER$								 NUMBER
ORA_ERR_MESG$									   VARCHAR2(2000)
ORA_ERR_ROWID$									 ROWID
ORA_ERR_OPTYP$									 VARCHAR2(2)
ORA_ERR_TAG$										  VARCHAR2(2000)
PKEY															  VARCHAR2(4000)
FIELD1														   VARCHAR2(4000)
FIELD2														   VARCHAR2(4000)



ملاحظة :
إذا لم يتم تعيين أسم للجدول سوف يتم تسميته بالاسم الافتراضي وهو ERR$_ متبوع باول 25 حرف من أسم الجدول.

تسجيل الخطأ:

عندما ينشأ الجدول لتسجيل أخطاء DML لجدول معين ,فإن كل ما يحتاج لتسجيل الأخطاء اتجاه ذلك الجدول هو إضافة عبارة تسجيل الخطأ للأمر insert أو update أو delete أو merge

Declare
i number;
Begin
i := 0;
while i <= 10 loop
insert into dmlel (pkey, field1, field2)
values (i, i, i)
LOG ERRORS INTO ERROR_LOG_DMLEL REJECT LIMIT 1;
i := i+1;
end loop;
End;
/
PL/SQL procedure successfully completed.



ملاحظة:
يجب معرفة أن عبارة REJECT LIMIT هي اختيارية فإن القيمة الافتراضية هي 0 لذا إذا لم يتم تحديد قيمة لـ REJECT LIMIT فستكون غير فعالة
وبهذه الطريقة تم إدخال جميع السجلات أما السجل الذي تسبب بالخطأ ora-12899لن يعيق عملية إدخال السجلات الأخرى ثم تم تسجيله إلى error_log_dmlel :

SQL>set lines 110
SQL> col num$ for 9999999  
SQL> col ora_err_mesg$ for a50
SQL> col ora_err_rowid$ for a25
SQL> col typ for a3 
SQL> col pkey for a4
SQL> col field1 for a4
SQL> select ora_err_number$ num$, ora_err_mesg$,
	  ora_err_rowid$, ora_err_optyp$ typ, pkey, field1 
	 from error_log_dmlel
SQL> /

  NUM$ ORA_ERR_MESG$									  ORA_ERR_ROWID$			TYP PKEY FIEL
---------- -------------------------------------------------- ------------------------- --- ---- ----------------------------
 12899  ORA-12899: value too large for column "BULKLOAD"."							   I	  10		10  
			DMLEL"."FIELD1" (actual: 2, maximum: 1)



مخرجات جملة السيلكت :

رقم الخطأ للأوراكل تم حفظه في ORA_ERR_NUMBER$ وأيضا الرسالة تم حفظها في ORA_ERR_MESG$ أما بالنسبة لـقيمة rowid فهي null لأن عملية الإدخال فشلت كما هو موضح لنوع العملية (ORA_ERR_OPTYP$ of I)حيث I يدل على Insert , لكن سيتم تسجيل قيم rowid للسجلات إذا كانت العمليات الفاشلة هي update,delete,merge .
أما بالنسبة لـ ORA_ERR_TAG$ فيستخدم في عنونة الخطأ و يمكن أن يستخدم لتمييز أي من البيانات قد سبب الخطأ وهنا مثال يوضح :

المثال :

في هذا المثال سوف نستخدم الحزمة DBMS_RANDOM لتوليد أرقام عشوائية من 0 إلى 9 في جملة الإدخال حيث سيدخل 101 , تدخل القيم في العمود dmlel.pkey الذي يحوي القيد primary key

declare 
i number;
begin
 i := 0;
dbms_random.initialize(2);
while i <= 100 loop
insert into dmlel (pkey, field1, field2)
values (trunc(dbms_random.value*10), 0, 0)
LOG ERRORS INTO ERROR_LOG_DMLEL ('Iteration number: ' || to_char(i))
REJECT LIMIT 1;
i := i+1;
end loop;
end;
/

ْ

SQL> select count(*) from dmlel;

 COUNT(*)
----------
	10

SQL> select count(*) from error_log_dmlel;

 COUNT(*)
----------
  91



من الملاحظ أن 10 سجلات تم إدخالها في الجدول بينما 91 سجل تم رفضهم .
الآن نستطيع تمييز من 101 ما هي العبارات التي تسببت بالخطأ من خلال ORA_ERR_TAG$ field :

نفذ السكربت التالي :

SQL>set lines 110
SQL> col num$ for 999999  
SQL> col ora_err_mesg$ for a65
SQL> col pkey for a4
SQL> col ora_err_tag$ for a25
SQL> ora_err_mesg$, pkey, ora_err_tag$
 from error_log_dmlel
 order by to_number(substr(ora_err_tag$,19,4))



بعد تنفيذ السكرت ستلاحظ في العمود ORA_ERR_TAG$ وجود رقم التكرار التابع لحلقة الدوران
وبهذه الطريقة تستطيع تمييز الأخطاء ومعرفة أي من الجمل قد تسببت بالخطأ .

تحياتي لكم ............ ترقبوا المرة القادمة ستكون هنالك مواضيع أكثر أهمية

رابط هذا التعليق
شارك

الأخ / sky information

اضافة متميزه .. من عضو متميز

شكرا لك .. وجزاك الله خيرا

لا تنسى

ترقبوا المرة القادمة ستكون هنالك مواضيع أكثر أهمية


فى انتظارك
رابط هذا التعليق
شارك

  • بعد 2 شهور...
  • بعد 4 أسابيع...

انضم إلى المناقشة

يمكنك المشاركة الآن والتسجيل لاحقاً. إذا كان لديك حساب, سجل دخولك الآن لتقوم بالمشاركة من خلال حسابك.

زائر
أضف رد على هذا الموضوع...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   تمت استعادة المحتوى السابق الخاص بك.   مسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

جاري التحميل
×
×
  • أضف...

برجاء الإنتباه

بإستخدامك للموقع فأنت تتعهد بالموافقة على هذه البنود: سياسة الخصوصية