从相同的一对多关系派生的多个列之间的唯一约束

时间:2017-03-29 23:01:07

标签: sql sql-server

我不确定我是否正确标题或者是否可能。

我有三列从另一个表中填充相同的一对多关系。

例如:

User_Id | Security Question 1 | Security Question 2 | Security Question 3

问题表:

Id | Question
1  | Are you x?
2  | Are you y?
3  | Are you z?

当一行写入第一个表时,它需要来自第二个表的安全问题。但是,可能的选择是第二个表格中的所有问题。我想强制执行一项限制,任何用户都没有选择任何问题两次。

我该怎么做?这应该降级到我的应用程序代码吗?

2 个答案:

答案 0 :(得分:1)

如果你将桌子标准化,那就很简单了。

create table t (
  UserId int
, QuestionOrdinal tinyint
, QuestionId int
, constraint uc_UserId_QuestionOrdinal unique (UserId, QuestionOrdinal)
, constraint uc_UserId_QuestionId unique (UserId, QuestionId)
);
insert into t values (1,1,1),(1,2,2);
insert into t values (1,3,1) -- constraint violation

rextester演示:http://rextester.com/FEHY66465

答案 1 :(得分:1)

这有点棘手。通常,将同一实体存储在多个列中是不合理的。这是一个可能有意义的案例。

您可以使用检查约束轻松完成所需操作:

alter table t add constraint check_t_security
    check (SecurityQuestion1 <> SecurityQuestion2 and
           SecurityQuestion2 <> SecurityQuestion3 and
           SecurityQuestion3 <> SecurityQuestion1 
          );

如果问题允许NULL值,则逻辑类似但更麻烦。您必须指定用户是否可以拥有多个NULL值。

您可以将逻辑缩短为:

alter table t add constraint check_t_security
    check (SecurityQuestion1 not in (SecurityQuestion2, SecurityQuestion3) and
           SecurityQuestion2 not in (SecurityQuestion3) 
          );