在 Oracle 中自定义 PL/SQL 异常

发布于 2024-08-18 06:30:21 字数 2275 浏览 12 评论 0原文

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

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

如果是这样,请向我展示一些代码,其中包含该函数引发的重要异常?

Frequently I found myself doing some functions to insert/delete/update in one or more tables and I've seen some expected exceptions been taken care of, like no_data_found, dupl_val_on_index, etc. For an insert like this:

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;

I would like to customize more of my exceptions or do an exception block for each select/insert. Is that possible or correct?

If so, could please show me some code with important exceptions being throwed by this function?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

姐不稀罕 2024-08-25 06:30:21

如果您只想替换自己的错误消息,可以使用 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 异常中)。 了解更多信息。

If you just want to substitute your own error message, there is RAISE_APPLICATION_ERROR...

When no_data_found then
    RAISE_APPLICATION_ERROR(-20000
                             , 'Insert Products: One of selects returned nothing';
                             , true);

The third parameter returns the original error as well as your custom one.

Oracle also gives us the option to define our exceptions. This can be useful if we want to pass the exception to a calling program...

Declare
    no_product_found exception;
Begin
    ....
When no_data_found then
    raise no_product_found;

This would be most effective if we defined the NO_PRODUCT_FOUND exception in a package specification where it could be referenced by external program units.

In addition, Oracle provides the INIT_EXCEPTION pragma which allows us to associate Oracle error numbers with our custom exceptions. Unfortunately we cannot overload error numbers which Oracle has already defined (for instance, we cannot create our own exceptions for ORA-1403 which is already covered by the NO_DATA_FOUND exception). Find out more.

绝不放开 2024-08-25 06:30:21
  • 在异常部分;您可以引发应用程序错误或返回 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)。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文