捕获唯一索引违例和raise_application_error

时间:2014-05-27 10:07:41

标签: exception oracle11g unique-constraint unique-index

是否可以捕获唯一索引违例和raise_application_error。我们尝试使用全局触发器并捕获异常,但是我们总是得到oracle异常。

  

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

我们在桌子上有一个基于功能的约束。

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:

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

1 个答案:

答案 0 :(得分:0)

触发器将在更新发生之前执行。由于在执行期间没有异常(它只是打印系统日期),因此不会引发异常。然后,实际执行更新,以及从数据库收到错误消息时的更新。

要捕获因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