我经常发现自己在一个或多个表中执行一些函数来插入/删除/更新,并且我已经看到了一些预期的异常,例如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;
我想自定义更多的异常或为每个select / insert执行异常块。这是可能的还是正确的?
如果是这样,请给我一些代码,但是这个函数会抛出一些重要的例外吗?
答案 0 :(得分:4)
如果您只想替换自己的错误消息,可以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提供了INIT_EXCEPTION编译指示,它允许我们将Oracle错误号与我们的自定义异常相关联。不幸的是,我们不能重载Oracle已经定义的错误号(例如,我们不能为NO_DATA_FOUND异常已经涵盖的ORA-1403创建我们自己的异常)。 Find out more.
答案 1 :(得分:1)
在例外部分;您可以引发应用程序错误或返回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)。