检查约束 - 如果另一列为真,则仅允许一列为真

Posted

技术标签:

【中文标题】检查约束 - 如果另一列为真,则仅允许一列为真【英文标题】:Check Constraint – only allow one column to be true if another column is true 【发布时间】:2013-03-10 23:40:29 【问题描述】:

以如下表为例:

CREATE TABLE [dbo].[tbl_Example](
    [PageID] [int] IDENTITY(1,1) NOT NULL,
    [RequireLogin] [bit] NOT NULL,
    [RequireAdmin] [bit] NOT NULL,
    [HideIfLoggedIn] [bit] NOT NULL
)

如何重写上述内容以包含如下检查约束:

如果[RequireLogin]False,则强制[RequireAdmin]False(即仅当@987654325 时[RequireAdmin]True @ 是 True,同时允许 [RequireLogin]True[RequireAdmin]False 如果[RequireLogin]False,则仅允许[HideIfLoggedIn]True

【问题讨论】:

(1) [RequireAdmin] 【参考方案1】:

您通常会在检查中执行嵌套的 case 语句,以使该类型的逻辑正常工作。请记住,支票中的案例必须仍然是评估,因此它会采用以下形式

CHECK (case when <exp> then 1 end = 1).

查看您的确切要求,但这似乎也可以工作并且可能更容易阅读:

 CREATE TABLE [dbo].[tbl_Example]
 (
    [PageID] [int] IDENTITY(1,1) NOT NULL,
    [RequireLogin] [bit] NOT NULL,
    [RequireAdmin] [bit] NOT NULL,
    [HideIfLoggedIn] [bit] NOT NULL
 )

 ALTER TABLE [dbo].[tbl_Example] ADD CONSTRAINT
     [RequireAdmin] CHECK 
      ((RequireAdmin = RequireLogin) OR 
      (RequireLogin=1));

 ALTER TABLE [dbo].[tbl_Example] ADD CONSTRAINT
      [HideIfLoggedIn] CHECK 
      ((RequireLogin=1 AND HideIfLoggedIn=0) OR 
       (RequireLogin=0 AND HideIfLoggedIn=1) OR 
       (RequireLogin=0 AND HideIfLoggedIn=0))

【讨论】:

不得不将最后一个更改为 ((RequireLogin=1 AND HideIfLoggedIn=0) OR (RequireLogin=0 AND HideIfLoggedIn=1) OR (RequireLogin=0 AND HideIfLoggedIn=0)) - 但是,效果很好 - 干杯 很好,组合的布尔逻辑总是很容易倒退。【参考方案2】:

如果我的代数正确:

alter table dbo.Example
add constraint RequireAdmin_RequireLogin_ck
check ( not ( RequireAdmin = 'true' and RequireLogin = 'false' ) ) ;
alter table dbo.Example
add constraint HideIfLoggedIn_RequireLogin_ck
check ( not ( HideIfLoggedIn = 'true' and RequireLogin = 'true' ) ) ;

请注意,这些检查约束是在表级别而不是列级别定义的,因为它们引用了多个列,所以必须这样做。由于这个原因,RThomas 的回答不是有效的 Transact-SQL!

【讨论】:

我推荐两件事:(1) 尽量不要使用NOT 来强制执行约束 - 它只是颠倒了你必须在精神上处理事情的方式 (2) 使用 0 和 1 而不是布尔样式的字符串用于 BIT 比较的文字。 我不同意你的观点,亚伦。首先,组织政策通常表示为否定的(例如,“不允许员工在工作时间浏览 ebay”),因此使用相同的措辞创建约束可以提供更好的阅读理解。其次,这些是布尔值——它们只是一个位字段,因为 MSSQL 没有布尔数据类型。使用“true”更适合阅读理解,因为它明确地向读者传达了“true”。相比之下,0 和 1 要求读者记住 0 在这种特定语言中是代表真还是假。 好吧,做你想做的,当然。我可以从 16 年的 SQL Server 经验告诉你,我提到的两件事让大多数用户感到困惑,无论他们对你有多大意义。 很好地将约束添加为更改表 - 我最初没有想到这一点。谢谢。

以上是关于检查约束 - 如果另一列为真,则仅允许一列为真的主要内容,如果未能解决你的问题,请参考以下文章

使用 when 语句创建更新触发器

如果列为空,SQLiteCursor 会做啥?

Postgres 9.2 - 添加条件约束检查

如果另一列为空,则选择一列

ORALCE表的约束条件

单击然后检查时如何设置字体真棒检查图标[关闭]