【问题标题】:Catch unique index violation and raise_application_error捕获唯一索引违规和 raise_application_error
【发布时间】:2014-05-27 10:07:40
【问题描述】:

是否可以捕获唯一索引违规和 raise_application_error。我们正在尝试使用一揽子触发器并捕获异常,但是我们总是遇到 oracle 异常。

ORA-00001:违反唯一约束 (TEST_UNIQUE_INDEX)

我们对表有一个基于 FUNCTION-BASED 的约束。

CREATE TABLE TEST_CONSTRAINT(
    "ID" NUMBER NOT NULL ENABLE, 
    "LOCATION" VARCHAR2(20) NOT NULL, 
    "DEPT" VARCHAR2(20) NOT NULL, 
    "RECORD" NUMBER NOT NULL)
/
CREATE UNIQUE INDEX TEST_UNIQUE_INDEX ON TEST_CONSTRAINT (
    CASE "RECORD" WHEN 1 THEN "LOCATION" ELSE NULL END, 
    CASE "RECORD" WHEN 1 THEN "DEPT"     ELSE NULL END)
/

更新触发代码之前

EXCEPTION 
  WHEN DUP_VAL_ON_INDEX THEN
      ERROR_MESSAGE := SQLERRM;
      DBMS_OUTPUT.PUT_LINE('SQLERRM '|| ERROR_MESSAGE);
  WHEN OTHERS THEN
      ERROR_MESSAGE := SQLERRM;
      DBMS_OUTPUT.PUT_LINE('SQLERRM '|| ERROR_MESSAGE);     
END;

test schema here

编辑 1:

这里的要求是强加选择性唯一性,即只能将一组位置/部门设置为记录(在应用程序中是布尔值)。在所有其他情况下,我们必须生成 raise_application_error。

【问题讨论】:

    标签: exception oracle11g unique-constraint unique-index


    【解决方案1】:

    触发器将在更新发生之前执行。由于在执行过程中不会出现异常(它所做的只是打印系统日期),因此不会引发异常。然后,实际执行了更新,这就是您从数据库中收到错误消息的时候。

    要捕获由于 UPDATE 语句而发生的异常,UPDATE 语句本身必须包含在 PL/SQL 块中,如下所示。

    DECLARE 
      V_DATE DATE;
      ERROR_MESSAGE VARCHAR2(1000); 
    BEGIN
      SELECT SYSDATE INTO V_DATE FROM DUAL;
      DBMS_OUTPUT.PUT_LINE('SYSDATE '|| V_DATE);
    
      UPDATE TEST_CONSTRAINT SET RECORD = 1 WHERE ID = 3;
    
    EXCEPTION 
      WHEN DUP_VAL_ON_INDEX THEN
          ERROR_MESSAGE := SQLERRM;
          DBMS_OUTPUT.PUT_LINE('Error occurred. SQLERRM '|| ERROR_MESSAGE);
      WHEN OTHERS THEN
          ERROR_MESSAGE := SQLERRM;
          DBMS_OUTPUT.PUT_LINE('SQLERRM '|| ERROR_MESSAGE);     
    END;
    /
    

    参考

    Handling PL/SQL Errors on Oracle® Database PL/SQL Language Reference

    【讨论】:

    • 我不能有 pl/sql 块,因为这些更新是从应用程序 api 触发的。因此我们需要捕获这些并显示适当的错误消息。
    • 如果可以在数据库中创建带有UPDATE语句的过程,那么可以调用该过程来执行UPDATE。或者,您可以考虑首先从应用程序 api 本身检查新值是否会导致“重复”行。如果他们愿意,那么您可以选择不执行 UPDATE。
    猜你喜欢
    • 1970-01-01
    • 2013-11-27
    • 2017-04-28
    • 1970-01-01
    • 1970-01-01
    • 2016-06-05
    • 2022-01-23
    • 1970-01-01
    • 2023-03-16
    相关资源
    最近更新 更多