SQL Check约束适用于所有行

时间:2017-03-20 09:09:31

标签: sql sql-server

所以我有这个表跟踪物品,有3种物品:

  • 武器
  • 护甲
  • 药水

我为那些创建了3个检查约束:

  • CK_Weapon:CHECK ([Type]=(1) AND NOT ([PhysDamage]+[ElemDamage])<(1) AND [AttackSpeed]>(0.5))
  • CK_Armour:CHECK ([Type]=(2) AND NOT ([PhysReduction]+[ElemReduction]<(1)))
  • CK_Potion:([Type]=(3) AND ([PhysDamage]+[ElemDamage])=(0) AND [AttackSpeed]=(0) AND ([PhysReduction]+[ElemReduction])=(0));

当我尝试添加含有以下插入物的药水时;

DECLARE @num int, @Type int, @Name varchar(50), @Description varchar(50), @Gold int

SET @Type = 3
SET @Name = 'Spirit Potion'
SET @Description = 'Restores a bit of Spirit'
SET @Gold = 150

insert into Item(Type, Name, Description, GoldValue) VALUES(@Type, @Name, @Description, @Gold)

我收到以下错误:

The INSERT statement conflicted with the CHECK constraint "CK_Weapon". The conflict occurred in database "Database", table "dbo.Item".

但它根本不应该触发这个CHECK,因为Potion Type应为3!
有没有一种简单的方法可以让我改变那些CHECK,这样它只会在Type相同的情况下触发?

2 个答案:

答案 0 :(得分:3)

您需要撤销支票的第一部分,以便他们提供&#34;通过&#34;对他们不关心的行。所以,例如对于装甲检查,您应该检查 {em> { Type(因此此检查约束不会护理)(适用于护甲的检查)通过:

2

重复进行其他检查。目前,您无法插入任何行,因为检查约束的组合要求CHECK ([Type]!=(2) OR (NOT ([PhysReduction]+[ElemReduction]<(1)))) 同时等于Type12

答案 1 :(得分:0)

您正在尝试将3个约束放在同一列上,希望它只触发其中一个,与您输入的Type匹配。但它会检查所有这些,这就是为什么CK_Weapon约束被违反,因为它期望Type = 1.

您可能想尝试在约束中编写一些case-logic,如下所示:

create table [RPGInventory]
(
      [Type] tinyint not null
    , [PhysDamage] int null
    , [ElemDamage] int null
    , [AttackSpeed] int null
    , [PhysReduction] int null
    , [ElemReduction] int null
    , constraint ckInventoryType check (1 = iif([Type] = (1)
                                                and not ([PhysDamage] + [ElemDamage]) < (1)
                                                and [AttackSpeed] > (0.5), 1
                                          , iif([Type] = (2)
                                                and not ([PhysReduction] + [ElemReduction] < (1)), 1
                                          , iif([Type] = (3)
                                                and ([PhysDamage] + [ElemDamage]) = (0)
                                                and [AttackSpeed] = (0)
                                                and ([PhysReduction] + [ElemReduction]) = (0), 1, 0)))
                                        )
)
go