2010-01-16 62 views
1

通常我发现自己在一个或多个表中执行了一些插入/删除/更新的功能,并且我已经看到一些预期的例外已被处理,如no_data_found,dupl_val_on_index等。像这样插入:自定义Oracle中的PL/SQL例外

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做一个异常块。这是可能的还是正确的?

如果是这样,请给我看一些代码,重要的例外是被这个函数抛出?

回答

1
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已经定义的错误数字(例如,我们不能为ORA-1403创建自己的例外,这已经被NO_DATA_FOUND例外所涵盖)。 Find out more.