【问题标题】:Constraint on multiple columns with specific values约束具有特定值的多列
【发布时间】:2012-10-25 21:38:24
【问题描述】:

我的架构有 3 列:ID1ID2Status

上面的每一列都是一个字符串。

我想创建一个如下约束:

不能有多个具有相同ID1ID2 的记录处于“未处理”状态。如果有多个记录具有相同的ID1ID2 且未处于 UNPROCESSED 状态,则可以。

是否可以在 SQL Server 中执行此操作?

【问题讨论】:

    标签: sql sql-server database constraints


    【解决方案1】:

    假设您使用的是 SQL Server 2008 或更高版本,您可以申请 filtered index

    CREATE UNIQUE INDEX UQ_Unprocessed_IDs ON UnnamedTable (ID1,ID2)
    WHERE (Status='Unprocessed')
    

    【讨论】:

      【解决方案2】:

      我不相信你可以通过约束来做到这一点。您需要在插入/更新操作上实现触发器。 SQL Server 的问题在于触发器是“AFTER”触发器。没有“BEFORE”触发器之类的东西(尽管有“INSTEAD OF”触发器类型。

      因此,您需要完成所有工作来执行事务,如果约束失败则对其进行审核并回滚,而不是简单地检查事务是否会导致违反约束。

      【讨论】:

        【解决方案3】:

        我会做一些事情,比如有一个名为 ProcessedId(而不是 Status)的列,并根据是否正在处理的 ID1 和 ID2 分配值。为了澄清,见下文

        [ID1, ID2, 进程 ID]

        SomeId1, SomeId2, -1
        SomeOtherId1, SomeOtherId2, 100304

        因此,任何未处理的 Id 集将始终具有 -1 的 ProcessId,阻塞和重复,并且任何已处理的 Id 集将被分配某种序列号,允许重复。有意义吗?

        所以继续我上面的例子,如果记录集再次进入未处理,它的 ProcessId 将是 -1 并导致 PK 违规。

        【讨论】:

          【解决方案4】:

          您可以使用一个视图来执行此操作,该视图是两个基础表的联合,一个用于处理的记录,一个用于未处理的报告。

          但是,视图本身不能更新,如果记录从已处理变回未处理,并且经常这样做,这将表现不佳。

          这也会让您对并行处理场景的思考更加复杂。

          上述两个限制都是因为您将某些更新替换为删除+插入。

          如果您至少有 SQL Server 2008,则过滤索引通常是更好的解决方案。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-10-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多