【问题标题】:Customize PL/SQL exceptions in Oracle在 Oracle 中自定义 PL/SQL 异常
【发布时间】:2010-01-16 18:34:52
【问题描述】:

我经常发现自己在一个或多个表中执行一些插入/删除/更新的功能,并且我已经看到一些预期的异常得到处理,例如no_data_founddupl_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;

我想自定义更多我的异常或为每个选择/插入做一个异常块。这是可能的还是正确的?

如果是这样,请给我看一些该函数抛出重要异常的代码吗?

【问题讨论】:

    标签: oracle nested exception plsqldeveloper


    【解决方案1】:

    如果你只是想替换你自己的错误信息,有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 pragma,它允许我们将 Oracle 错误编号与我们的自定义异常相关联。不幸的是,我们不能重载 Oracle 已经定义的错误编号(例如,我们不能为 ORA-1403 创建自己的异常,它已经被 NO_DATA_FOUND 异常覆盖)。 Find out more.

    【讨论】:

      【解决方案2】:
      • 在异常部分;您可以引发应用程序错误或返回 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)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-07
        • 1970-01-01
        相关资源
        最近更新 更多