当违反 Oracle 约束时,设置默认值?我该怎么做呢?

When Oracle constraint is violated, set default? How do I do this?

我在设置 Oracle 数据库中的默认值时遇到一些问题。

我想将我所在地区的默认值设置为 NW:region CHAR(2) DEFAULT ('NW'),

我还进行了参考检查,以确保区域中的所有值都是 2 个字符: CONSTRAINT check_region CHECK (region IN ('N', 'NW', 'NE', 'S', 'SE', 'SW', 'W', 'E')));

但是,当我插入不符合我的约束条件的数据时,我遇到了这个错误。我有一行数据,其中有一个值 'NULL',所以它不应该被插入......但它应该默认为 NW 的默认值......对吧?

Error starting at line : 16 in command -
INSERT into acctmanager
 (amid, amfirst, amlast, amedate, amsal, amcomm, region) VALUES ('L500','MANDY','LOPEZ','01-OCT-09', 47000, 1500, 'NULL')
Error report -
ORA-02290: check constraint (SYS.CHECK_REGION) violated

我知道应该会弹出错误...但是该值不应该默认为我在架构中为 region 定义的值吗?我已经尝试查看 here,但我仍然遇到插入错误。

有什么建议吗?

这是我的整个创建 table 语句:

DROP TABLE ACCTMANAGER CASCADE CONSTRAINTS;

CREATE TABLE acctmanager
(amid CHAR(4),
 amfirst VARCHAR2(12)  NOT NULL,
 amlast VARCHAR2(12)  NOT NULL,
 amedate DATE DEFAULT SYSDATE NOT NULL,
 amsal NUMBER(8,2),
 amcomm NUMBER(7,2),
 region CHAR(4) DEFAULT ('NW'),
  CONSTRAINT PK_acctmanager PRIMARY KEY (amid),
  CONSTRAINT check_region CHECK (region IN ('N', 'NW', 'NE', 'S', 'SE', 'SW', 'W', 'E')));

INSERT into acctmanager
 (amid, amfirst, amlast, amedate, amsal, amcomm, region) VALUES ('T500','NICK','TAYLOR','05-SEP-09', 42000, 3500, 'NE');
INSERT into acctmanager
 (amid, amfirst, amlast, amedate, amsal, amcomm, region) VALUES ('L500','MANDY','LOPEZ','01-OCT-09', 47000, 1500, 'NULL');
INSERT into acctmanager
 (amid, amfirst, amlast, amedate, amsal, amcomm, region) VALUES ('J500','SAMMIE','JONES','DEFAULT' , 39500, 2000, 'NW');
VALUES ('L500','MANDY','LOPEZ','01-OCT-09', 47000, 1500, 'NULL')

不是'NULL',而是NULL(没有单引号)。

[编辑]

这是一个触发器示例:

SQL> create table test
  2    (id      number,
  3     region  varchar2(2) default 'NW'
  4    );

Table created.

SQL> create or replace trigger trg_biu_test
  2    before insert or update on test
  3    for each row
  4  begin
  5    if :new.region not in ('N', 'NW', 'NE') then
  6       :new.region := 'NW';
  7    end if;
  8  end;
  9  /

Trigger created.

测试:如果 REGION 名称比 VARCHAR2 长(因为这是声明列的方式,无论触发器如何,插入都会失败):

SQL> insert into test (id, region) values (1, 'what?');
insert into test (id, region) values (1, 'what?')
*
ERROR at line 1:
ORA-12899: value too large for column "SCOTT"."TEST"."REGION" (actual: 5, maximum: 2)

短一点(最多 2 个字符)即可:

SQL> insert into test (id, region) values (1, 'xx');

1 row created.

将 NULL 插入区域实际上会插入默认值:

SQL> insert into test (id) values (2);

1 row created.

SQL>
SQL> select * From test;

        ID RE
---------- --
         1 NW
         2 NW

SQL>

[编辑 #2:DEFAULT 关键字]

另一种选择是使用 DEFAULT 关键字,例如

SQL> insert into test (id, region) values (3, default);

1 row created.

SQL> select * From test where id = 3;

        ID RE
---------- --
         3 NW

感谢 Wernfried 的评论。

您可以使用 select from dual 代替 values 关键字。这使 nvl 发挥作用。

所以,而不是这个:

insert into table
(field1, field2, etc)
values
(value1, value2, etc)

这样做:

insert into table
(field1, field2, etc)
select nvl(field1, default value1)
, nvl(field2, default value2)
, etc
from dual