如何在 PL/SQL 中捕获约束冲突?

Posted

技术标签:

【中文标题】如何在 PL/SQL 中捕获约束冲突?【英文标题】:How to catch constraint violation in PL/SQL? 【发布时间】:2014-04-23 08:45:34 【问题描述】:
CREATE TABLE LOCATION (
  LOCID VARCHAR2(5)
, MINQTY    NUMBER
, MAXQTY    NUMBER
, PRIMARY KEY   (LOCID)
, CONSTRAINT CHECK_LOCID_LENGTH CHECK (LENGTH(LOCID) = 5)
, CONSTRAINT CHECK_MINQTY_RANGE CHECK (MINQTY BETWEEN 0 AND 999)
, CONSTRAINT CHECK_MAXQTY_RANGE CHECK (MAXQTY BETWEEN 0 AND 999)
, CONSTRAINT CHECK_MAXQTY_GREATER_MIXQTY CHECK (MAXQTY >= MINQTY)
);


CREATE OR REPLACE PROCEDURE ADD_LOCATION_TO_DB(ploccode VARCHAR2, pminqty NUMBER, pmaxqty NUMBER) AS
BEGIN
INSERT INTO location(locid, minqty, maxqty) VALUES (ploccode, pminqty, pmaxqty);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
RAISE_APPLICATION_ERROR(-20081, 'Duplicate Location ID');
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20086,sqlerrm);
END;

我创建了带有约束的上表。 现在我想通过在异常中捕获它们来测试 PL/SQL 过程中的这些约束。但我很困惑如何做到这一点。

【问题讨论】:

sql-server 不使用 PL/SQL。你需要它和oracle 的解决方案吗? 我想要一个在位置表中插入一行的过程的 PL/SQL 代码,并希望测试该 pl/sql 过程中的约束。但我不确定如何检查约束的代码。 是的,但是您已经用两种不同产品标记了这个问题,其中一种产品甚至没有PL/SQL。您真的需要针对这两种产品的解决方案吗? 我删除了 sql-server 标签,因为问题显然是关于 Oracle 和 PL/SQL 的。 检查约束违规没有预定义的异常(见这里:docs.oracle.com/cd/E11882_01/appdev.112/e25519/…)您需要检查when others处理程序中的错误代码 【参考方案1】:

违反检查约束时发生的错误是 ORA-02290。尽管对此没有“标准”定义,但声明自己的异常很容易,因此您可以在抛出 -2290 时捕获它。假设我们创建了一个表,如下所示:

CREATE TABLE SOME_TABLE (COL1 CHAR(1) CHECK(COL1 IN ('Y', 'N')));

然后我们运行以下代码块:

DECLARE
  -- First, declare and initialize an appropriate exception

  CHECK_CONSTRAINT_VIOLATED EXCEPTION;
  PRAGMA EXCEPTION_INIT(CHECK_CONSTRAINT_VIOLATED, -2290);
BEGIN
  INSERT INTO SOME_TABLE(COL1) VALUES ('X');  -- will violate the check constraint
  RETURN;
EXCEPTION
  WHEN CHECK_CONSTRAINT_VIOLATED THEN  -- catch the ORA-02290 exception
    DBMS_OUTPUT.PUT_LINE('INSERT failed due to check constraint violation');
  WHEN OTHERS THEN                     -- catch all other exceptions
    DBMS_OUTPUT.PUT_LINE('Something else went wrong - ' || SQLCODE ||
                         ' : ' || SQLERRM);
END;

如果您按前面所示创建表,然后运行上面的块,您会发现 DBMS_OUTPUT 上会显示“INSERT failed due to check constraint violation”行。

分享和享受。

【讨论】:

如果表有多个检查约束,有没有办法识别违反了哪个约束? 我相信约束的名称将与其他文本一起出现在 SQLERRM 中。您可以如上所示打印 SQLERRM,或解析文本以找到约束名称。

以上是关于如何在 PL/SQL 中捕获约束冲突?的主要内容,如果未能解决你的问题,请参考以下文章

Oracle PL/SQL - 如何在异常子句的单独表中捕获坏数据?

如何从 oracle pl sql 中的包主体内的 select 语句中捕获特定列

PL/SQL:捕获编号异常?

pl/sql 触发器完整性约束问题

如何在 Oracle PL/SQL 上创建可以捕获 DUP_VAL_ON_INDEX 的前触发器或后触发器

在 PL/SQL 包中声明全局异常