当违反 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
我在设置 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