约束违反异常 PL/SQL
Posted
技术标签:
【中文标题】约束违反异常 PL/SQL【英文标题】:constraint violation exception PL/SQL 【发布时间】:2018-03-04 20:27:02 【问题描述】:我目前正在处理一项任务,我需要创建一个匿名块来处理违反约束(违规是更新的信用卡数量太少)。我创建了以下不引发错误的块,它只返回约束违规。知道为什么它没有引发我的异常吗?
DECLARE
my_excep EXCEPTION;
BEGIN
UPDATE mm_member
SET credit_card = '123456789'
WHERE member_id = '14';
IF SQL%ROWCOUNT = 0 THEN
RAISE my_excep;
END IF;
EXCEPTION
WHEN my_excep THEN
DBMS_OUTPUT.PUT_LINE('Failed to update.');
END;
这里创建表
CREATE TABLE mm_member
(member_id NUMBER(4),
last VARCHAR(12),
first VARCHAR(8),
license_no VARCHAR(9),
license_st VARCHAR(2),
credit_card VARCHAR(12),
suspension VARCHAR(1) DEFAULT 'N',
mailing_list VARCHAR(1),
CONSTRAINT cust_custid_pk PRIMARY KEY (member_id),
CONSTRAINT cust_credcard_ck CHECK (LENGTH(credit_card) = 12));
executed block
【问题讨论】:
【参考方案1】:您编写的代码完全符合预期 - 如果它没有更新任何内容,则会引发异常,该异常只会执行 DBMS_OUTPUT.PUT_LINE 并显示“更新失败”。
你期望它做什么?
如果您打算真正引发一个异常,您应该这样做(而不是 DBMS_OUTPUT):
raise_application_error(-20000, 'Failed to update');
不过,您所写的任何内容都没有您所描述的,即
违规是更新的信用卡号码太少
这可以使用真正的约束来完成,例如
create table mm_member
( member_id varchar2(2)
credit_card varchar2(20) constraint ch_cc check (length(credit_card) = 9),
);
虽然在我看来,这似乎是一个非常低效的检查。
[编辑:提高示范]
SQL> create table mm_member
2 ( member_id varchar2(2),
3 credit_card varchar2(20)
4 );
Table created.
SQL> insert into mm_member (member_id, credit_card) values ('14', '1234');
1 row created.
SQL> -- this will work because there's MEMBER_ID = 14 in the table
SQL> DECLARE
2 my_excep EXCEPTION;
3 BEGIN
4 UPDATE mm_member
5 SET credit_card = '123456789'
6 WHERE member_id = '14';
7
8 IF SQL%ROWCOUNT = 0 THEN
9 RAISE my_excep;
10 END IF;
11 EXCEPTION
12 WHEN my_excep THEN
13 --DBMS_OUTPUT.PUT_LINE('Failed to update.');
14 raise_application_error(-20000, 'Failed to update');
15 END;
16 /
PL/SQL procedure successfully completed.
好的;现在失败了:
SQL> -- changing '14' to something else (for example, '15') will raise an exception
SQL> l6
6* WHERE member_id = '14';
SQL> c/14/15
6* WHERE member_id = '15';
SQL> /
DECLARE
*
ERROR at line 1:
ORA-20000: Failed to update --> see? This is an exception
ORA-06512: at line 14
SQL>
[编辑#2:拦截检查约束违规]
由于违反检查约束,这将失败:注意 ORA-02290 错误代码:
SQL> update mm_member set credit_card = '123';
update mm_member set credit_card = '123'
*
ERROR at line 1:
ORA-02290: check constraint (SCOTT.CH_CC) violated
您的代码,修改为通过声明 PRAGMA EXCEPTION_INIT
来拦截它使用相同的 2290 错误代码:
SQL> DECLARE
2 my_excep EXCEPTION;
3 pragma exception_init (my_excep, -2290);
4 BEGIN
5 UPDATE mm_member
6 SET credit_card = '123456789'
7 WHERE member_id = '14';
8
9 IF SQL%ROWCOUNT = 0 THEN
10 RAISE my_excep;
11 END IF;
12 EXCEPTION
13 WHEN my_excep THEN
14 DBMS_OUTPUT.PUT_LINE('I intercepted check constraint - failed to update.');
15 END;
16 /
I intercepted check constraint - failed to update.
PL/SQL procedure successfully completed.
SQL>
【讨论】:
它不会引发异常并在我运行它时执行 DBMS 输出。它仍然返回约束冲突。 哪个约束?在任何地方,您的代码中都没有实际的约束。请编辑您的问题并包含CREATE TABLE
声明。同时,我编辑了我的消息并演示了发生了什么。
添加了创建表。如您所见,违反约束是因为新的信用卡号太短(这是故意的,我的任务是创建一个块,但该错误除外)
啊哈。因此,您已经对该列有 CHECK 约束。很好,这就是它应该做的方式。您计划在 PL/SQL 块中使用的异常无效,因为 CHECK 约束首先失败,一旦您尝试将信用卡号更新为长度不同于 12 个字符的值。你的 MY_EXCEP 没有机会提升,Oracle 的内置更快。从我的角度来看,一切都按预期进行。如果您想引发自己的异常,则必须禁用该列上的检查约束。
似乎是 IMO 的冗余分配......所以如果我想绕过 oracles 约束违规返回并拥有自己的 DBMS 输出......我最好的选择是什么?这是确切的分配问题:为此 SQL 命令生成的错误创建一个异常:更新 mm_member set credit_card = 123456789 where member_id = 14;以上是关于约束违反异常 PL/SQL的主要内容,如果未能解决你的问题,请参考以下文章