在两个可空的FK之间添加SQL XOR约束

时间:2012-06-20 20:07:29

标签: sql sql-server-2005 database-design

我想在一个表中定义两个可空FK之间的约束,其中如果一个为空,另一个需要一个值,但两者都不能为空,两者都不能有值。逻辑是派生表从任一FK表继承数据以确定其类型。另外,对于有趣的奖励积分,这是一个坏主意吗?

3 个答案:

答案 0 :(得分:14)

实现它的一种方法是简单地写下“异或”实际意味着什么:

CHECK (
    (FK1 IS NOT NULL AND FK2 IS NULL)
    OR (FK1 IS NULL AND FK2 IS NOT NULL)
)

但是,如果你有很多FK,上面的方法会很快变得难以处理,在这种情况下你可以这样做:

CHECK (
    1 = (
        (CASE WHEN FK1 IS NULL THEN 0 ELSE 1 END)
        + (CASE WHEN FK2 IS NULL THEN 0 ELSE 1 END)
        + (CASE WHEN FK3 IS NULL THEN 0 ELSE 1 END)
        + (CASE WHEN FK4 IS NULL THEN 0 ELSE 1 END)
        ...
    )
)

BTW,该模式有合法用途,例如this one(尽管由于缺少延迟约束而不适用于MS SQL Server)。在您的特定情况下是否合法,我无法根据您目前提供的信息进行判断。

答案 1 :(得分:1)

您可以使用check constraint

create table #t (
   a int,
   b int);

alter table #t add constraint c1 
check ( coalesce(a, b) is not null and a*b is null );

insert into #t values ( 1,null);

insert into #t values ( null ,null);

运行:

The INSERT statement conflicted with the CHECK constraint "c1". 

答案 2 :(得分:0)

替代方法是在过程中定义此检查约束。在派生表中插入记录之前,应该满足约束。否则插入失败或返回错误。