Oracle での PL/SQL 例外のカスタマイズ
-
21-09-2019 - |
質問
頻繁に、1 つまたは複数のテーブルで挿入/削除/更新する関数を実行していることに気づきましたが、次のような予期された例外が処理されていることがわかりました。 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 を返すことができます。それはあなたの選択にかかっています。
エラーを例外セクション (またはメイン セクション) に記録したい場合は、AUTONOMOUS TRANSACTION を使用して独自のログ プロシージャを作成します。したがって、ロギング メカニズムはメイン トランザクションの COMMIT または ROLLBACK の影響を受けません。(見る: http://www.dba-oracle.com/t_autonomous_transaction.htm)
Oracle 10gR2 (以降) の別のロギング メカニズム (DML エラー ログ) は、LOG ERRORS 句です (以下を参照)。 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);
3番目のパラメータは、元のエラーだけでなく、あなたのカスタム1を返します。
Oracleはまた、私たちの例外を定義するためのオプションを提供します。我々は呼び出し元のプログラムに例外を渡したい場合に便利です...
Declare
no_product_found exception;
Begin
....
When no_data_found then
raise no_product_found;
私たちは、それが外部のプログラム単位で参照することができ、パッケージ仕様でNO_PRODUCT_FOUND例外を定義した場合、これは最も効果的であろう。
また、オラクルは、私たちは私たちのカスタム例外をOracleエラー番号を関連付けることができますINIT_EXCEPTIONプラグマを提供します。残念ながら、私たちは、(例えば、我々はすでにNO_DATA_FOUND例外で覆われているORA-1403のための当社独自の例外を作成することはできません)Oracleは、すでに定義されたエラー番号をオーバーロードすることはできません。 詳細をご覧ください。に