تخصيص استثناءات PL/SQL في Oracle
-
21-09-2019 - |
سؤال
في كثير من الأحيان وجدت نفسي أقوم ببعض الوظائف لإدراج/حذف/تحديث في واحد أو أكثر من الجداول ورأيت بعض الاستثناءات المتوقعة تم الاعتناء بها ، مثل no_data_found
, dupl_val_on_index
, ، إلخ. لإدراج مثل هذا:
create or replace FUNCTION "INSERT_PRODUCTS" (
a_supplier_id IN FORNECEDOR.ID_FORNECEDOR%TYPE,
a_prodArray IN OUT PRODTABLE
)
RETURN NUMBER IS
v_error_code NUMBER;
v_error_message VARCHAR2(255);
v_result NUMBER:= 0;
v_prod_id PRODUTO.ID_PROD%TYPE;
v_supplier FORNECEDOR%ROWTYPE;
v_prodInserted PROD_OBJ;
newList prodtable := prodtable();
BEGIN
SELECT FORNEC_OBJ(ID_FORNECEDOR,NOME_FORNECEDOR,MORADA,ARMAZEM,EMAIL,TLF,TLM,FAX) into v_supplier from fornecedor where id_fornecedor = a_supplier_id;
FOR i IN a_prodArray.FIRST .. a_prodArray.LAST LOOP
INSERT INTO PRODUTO (PRODUTO.ID_PROD,PRODUTO.NOME_PROD,PRODUTO.PREC_COMPRA_PROD,PRODUTO.IVA_PROD,PRODUTO.PREC_VENDA_PROD,PRODUTO.QTD_STOCK_PROD,PRODUTO.QTD_STOCK_MIN_PROD)
VALUES (S_PRODUTO.nextval,a_prodArray(i).NOME_PROD,a_prodArray(i).PREC_COMPRA_PROD,a_prodArray(i).IVA_PROD,NULL,NULL,NULL);
/* If the above insert didn't failed, we can insert in weak entity PROD_FORNECIDO. */
SELECT ID_PROD into v_prod_id from PRODUTO where NOME_PROD = a_prodArray(i).NOME_PROD;
INSERT INTO PROD_FORNECIDO VALUES (a_supplier_id, v_prod_id,a_prodArray(i).PREC_COMPRA_PROD);
SELECT PROD_OBJ(ID_PROD,NOME_PROD,PREC_COMPRA_PROD,PREC_VENDA_PROD,QTD_STOCK_PROD,QTD_STOCK_MIN_PROD,IVA_PROD) into v_prodInserted from PRODUTO where ID_PROD= v_prod_id;
a_prodarray(i).ID_PROD := v_prod_id;
END LOOP;
INSERT INTO FORNECPRODS VALUES (a_supplier_id,v_supplier, a_prodarray);
v_result:= 1;
RETURN v_result;
COMMIT;
Exception
When no_data_found then
v_error_code := 0;
v_error_message:= 'Insert Products: One of selects returned nothing';
Insert Into errors Values (v_error_code,v_error_message, systimestamp);
RETURN v_result;
When others Then
ROLLBACK;
v_error_code := SQLCODE;
v_error_message:=substr(SQLERRM,1,50);
Insert Into errors Values (v_error_code,'Error inserting products list',systimestamp);
RETURN v_result;
END;
أرغب في تخصيص المزيد من استثناءاتي أو إجراء كتلة استثناء لكل تحديد/إدراج. هل هذا ممكن أم صحيح؟
إذا كان الأمر كذلك ، فهل يمكن أن تريني بعض التعليمات البرمجية مع استثناءات مهمة ترميها هذه الوظيفة؟
المحلول
في قسم الاستثناء ؛ يمكنك رفع خطأ التطبيق أو إرجاع 0 مع شرح رمز الخطأ. إنه عن اختيارك.
إذا كنت ترغب في تسجيل أخطاءك في قسم الاستثناء (أو في القسم الرئيسي) ، فاكتب إجراء التسجيل الخاص بك باستخدام معاملة مستقلة. لذلك ، لا تتأثر آلية التسجيل الخاصة بك بالتزام المعاملة الرئيسية أو التراجع. (يرى: http://www.dba-oracle.com/t_autonomous_transaction.htm)
آلية تسجيل أخرى (سجل خطأ DML) في Oracle 10GR2 (وما فوق) هو شرط أخطاء السجل (انظر: http://www.oracle-base.com/articles/10g/dmlerrorlogging_10gr2.php).
نصائح أخرى
إذا كنت تريد فقط استبدال رسالة الخطأ الخاصة بك ، فهناك RAISE_APPLICATION_ERROR
...
When no_data_found then
RAISE_APPLICATION_ERROR(-20000
, 'Insert Products: One of selects returned nothing';
, true);
تقوم المعلمة الثالثة بإرجاع الخطأ الأصلي وكذلك الخط المخصص.
يعطينا Oracle أيضًا خيار تحديد استثناءاتنا. قد يكون هذا مفيدًا إذا أردنا نقل الاستثناء إلى برنامج الاتصال ...
Declare
no_product_found exception;
Begin
....
When no_data_found then
raise no_product_found;
سيكون هذا أكثر فعالية إذا حددنا استثناء No_Product_Found في مواصفات الحزمة حيث يمكن الرجوع إليها بواسطة وحدات البرنامج الخارجية.
بالإضافة إلى ذلك ، يوفر Oracle Pragma init_exception والذي يسمح لنا بربط أرقام خطأ Oracle مع استثناءاتنا المخصصة. لسوء الحظ ، لا يمكننا أن لا نستطيع أن نحدد أرقام الأخطاء التي حددها Oracle بالفعل (على سبيل المثال ، لا يمكننا إنشاء استثناءاتنا الخاصة لـ ORA-1403 والتي تم تغطيتها بالفعل بواسطة استثناء No_data_found). اكتشف المزيد.