Personnaliser les exceptions PL / SQL dans Oracle
-
21-09-2019 - |
Question
Souvent je me suis retrouvé à faire certaines fonctions pour insérer / supprimer / mettre à jour dans une ou plusieurs tables et je l'ai vu quelques exceptions prévues été pris en charge, comme no_data_found
, dupl_val_on_index
, etc. Pour un insert comme ceci:
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;
Je voudrais personnaliser plus de mes exceptions ou faire un bloc d'exception pour chaque sélection / insert. Est-ce possible ou pas?
Si oui, pourriez s'il vous plaît me montrer un peu de code avec des exceptions importantes étant par cette fonction jetèrent?
La solution
-
Dans la section d'exception; vous pouvez augmenter erreur d'application ou retourner 0 avec le code d'erreur explication. Il est de votre choix.
-
Si vous voulez enregistrer vos erreurs dans la section d'exception (ou dans la section principale), écrivez votre propre procédure d'enregistrement avec TRANSACTION AUTONOME. donc, votre mécanisme de journalisation n'est pas affecté par ou ROLLBACK de COMMIT votre transaction principale. (Voir: http://www.dba-oracle.com/t_autonomous_transaction.htm )
-
est erreurs de journal clause Un autre mécanisme de journalisation (DML Error Log) dans Oracle 10gR2 (et au-dessus) (voir: http://www.oracle-base.com/articles/10g/DmlErrorLogging_10gR2.php ).
Autres conseils
Si vous voulez juste de remplacer votre propre message d'erreur, il est RAISE_APPLICATION_ERROR
...
When no_data_found then
RAISE_APPLICATION_ERROR(-20000
, 'Insert Products: One of selects returned nothing';
, true);
Le troisième paramètre renvoie l'erreur d'origine ainsi que votre une sur mesure.
Oracle nous donne aussi la possibilité de définir nos exceptions. Cela peut être utile si nous voulons passer l'exception à un programme appelant ...
Declare
no_product_found exception;
Begin
....
When no_data_found then
raise no_product_found;
Ce serait plus efficace si nous avons défini l'exception NO_PRODUCT_FOUND dans une spécification de package où il pourrait être référencé par des unités de programmes externes.
En outre, Oracle fournit la pragma INIT_EXCEPTION qui nous permet d'associer les numéros d'erreur Oracle avec nos exceptions personnalisées. Malheureusement, nous ne pouvons pas surcharger les numéros d'erreur qui Oracle a déjà défini (par exemple, nous ne pouvons pas créer nos propres exceptions pour ORA-1403 qui est déjà couvert par l'exception NO_DATA_FOUND). En savoir plus.