【发布时间】:2012-10-25 21:38:24
【问题描述】:
我的架构有 3 列:ID1、ID2、Status
上面的每一列都是一个字符串。
我想创建一个如下约束:
不能有多个具有相同ID1 和ID2 的记录处于“未处理”状态。如果有多个记录具有相同的ID1 和ID2 且未处于 UNPROCESSED 状态,则可以。
是否可以在 SQL Server 中执行此操作?
【问题讨论】:
标签: sql sql-server database constraints
我的架构有 3 列:ID1、ID2、Status
上面的每一列都是一个字符串。
我想创建一个如下约束:
不能有多个具有相同ID1 和ID2 的记录处于“未处理”状态。如果有多个记录具有相同的ID1 和ID2 且未处于 UNPROCESSED 状态,则可以。
是否可以在 SQL Server 中执行此操作?
【问题讨论】:
标签: sql sql-server database constraints
假设您使用的是 SQL Server 2008 或更高版本,您可以申请 filtered index:
CREATE UNIQUE INDEX UQ_Unprocessed_IDs ON UnnamedTable (ID1,ID2)
WHERE (Status='Unprocessed')
【讨论】:
我不相信你可以通过约束来做到这一点。您需要在插入/更新操作上实现触发器。 SQL Server 的问题在于触发器是“AFTER”触发器。没有“BEFORE”触发器之类的东西(尽管有“INSTEAD OF”触发器类型。
因此,您需要完成所有工作来执行事务,如果约束失败则对其进行审核并回滚,而不是简单地检查事务是否会导致违反约束。
【讨论】:
我会做一些事情,比如有一个名为 ProcessedId(而不是 Status)的列,并根据是否正在处理的 ID1 和 ID2 分配值。为了澄清,见下文
[ID1, ID2, 进程 ID]
SomeId1, SomeId2, -1
SomeOtherId1, SomeOtherId2, 100304
因此,任何未处理的 Id 集将始终具有 -1 的 ProcessId,阻塞和重复,并且任何已处理的 Id 集将被分配某种序列号,允许重复。有意义吗?
所以继续我上面的例子,如果记录集再次进入未处理,它的 ProcessId 将是 -1 并导致 PK 违规。
【讨论】:
您可以使用一个视图来执行此操作,该视图是两个基础表的联合,一个用于处理的记录,一个用于未处理的报告。
但是,视图本身不能更新,如果记录从已处理变回未处理,并且经常这样做,这将表现不佳。
这也会让您对并行处理场景的思考更加复杂。
上述两个限制都是因为您将某些更新替换为删除+插入。
如果您至少有 SQL Server 2008,则过滤索引通常是更好的解决方案。
【讨论】: