2012-09-15 101 views
4

我有一个表叫Room,它有列(ID,型号,价格...等)检查约束列之间值检查

我要添加约束双方typeprice这样的:

  • 如果单个(或多个),那么价格不应该大于50,
  • 如果双(d),则价格不应该大于100,和
  • 如果家族(f)中,然后价格应该不会更大比150

我试图像这样添加它,但它给我一个错误。不知道我应该怎么写这样的:

ALTER TABLE ROOM 
ADD (CONSTRAINT CHK_PRICE CHECK (
(TYPE='S' AND PRICE <= 50) AND 
(TYPE='D' AND PRICE <=100) AND 
(TYPE='F' AND PRICE <= 150))); 

收到的错误是:

SQL Error: ORA-02293: cannot validate (xxxx.CHK_PRICE) - check 
constraint violated 
02293. 00000 - "cannot validate (%s.%s) - check constraint violated" 
*Cause: an alter table operation tried to validate a check constraint to 
      populated table that had nocomplying values. 
*Action: Obvious 
+0

nop ....所有价格都低于他们的要求值 – user1672735

+0

@ user1672735 - 你怎么知道的?该错误清楚地表明'*原因:一个alter table操作试图验证一个检查约束,以填充表中有不合适的值。 – Annjawn

回答

10

这听起来像你需要OR在一起的三个条件,不AND在一起。这是不可能的任何行,以满足所有三个criteria-- type不能同时具备S,d的值,和F.你可能想

ALTER TABLE ROOM 
    ADD (CONSTRAINT CHK_PRICE CHECK (
     (TYPE='S' AND PRICE <= 50) OR -- <-- OR, not AND 
     (TYPE='D' AND PRICE <= 100) OR -- <-- OR, not AND 
     (TYPE='F' AND PRICE <= 150))); 
+2

@ user1672735可能还希望/需要添加条件(在此检查约束中或在单独的非空约束中)来处理或防止“TYPE”和/或“PRICE”为空的情况。例如,如果“TYPE”或“PRICE”为空(这可能不是预期的),那么发布的修改约束本身不会阻止插入行。 –

+0

是加入或做的工作....谢谢! – user1672735

2

那么,你就需要使用“或”,而不是“和“在你的三个检查条件。

并且错误消息(ORA-02293:无法验证)通知您的表空间中存在违反完整性约束条件的一些数据行。另外,您可以指定表中的现有数据是否必须符合约束条件,而不是使用VALIDATE或NOVALIDATE选项。 如果您不想在室内验证这些现有数据行,则可以使用NOVALIDATE指定此约束,并且VALIDATE为默认值。

ALTER TABLE ROOM  
    ADD (CONSTRAINT CHK_PRICE CHECK 
    (
    (TYPE='S' AND PRICE <= 50) OR -- <-- OR, not AND 
    (TYPE='D' AND PRICE <= 100) OR -- <-- OR, not AND 
    (TYPE='F' AND PRICE <= 150) 
    ) 
    NOVALIDATE -- VALIDATE is default 
    ); 
1

您收到错误消息ORA-02293,因为你已经在你的表中的数据不符合新创建的检查约束。

我认为这里的一个重要部分是意识到你没有一个业务规则来验证这里,但三个。对于验证约束条件的用户来说,确切地知道他插入的行有什么问题是最方便的。所以这就是为什么我会去这些约束:

SQL> create table room (id,type,price) 
    2 as 
    3 select 1, 'S', 50 from dual union all 
    4 select 2, 'D', 80 from dual union all 
    5 select 3, 'F', 110 from dual 
    6/

Table created. 

SQL> alter table room add constraint single_room_below_50 check (type != 'S' or price <= 50) 
    2/

Table altered. 

SQL> alter table room add constraint double_room_below_100 check (type != 'D' or price <= 100) 
    2/

Table altered. 

SQL> alter table room add constraint family_room_below_150 check (type != 'F' or price <= 150) 
    2/

Table altered. 

SQL> insert into room values (4, 'S', 60) 
    2/
insert into room values (4, 'S', 60) 
* 
ERROR at line 1: 
ORA-02290: check constraint (RWIJK.SINGLE_ROOM_BELOW_50) violated 

问候,
罗布。

PS:关于此主题的更多背景信息请参见this blogpost of mine