【发布时间】:2009-06-18 13:48:53
【问题描述】:
我正在寻找向表添加约束的最佳方式,该约束实际上是记录与该表中其余记录之间关系的唯一索引。
想象下表描述了各种警卫的巡逻(来自之前的守望者场景)
PK PatrolID Integer
FK GuardID Integer
Starts DateTime
Ends DateTime
我们从一个约束开始,指定开始和结束时间必须是合乎逻辑的:
Ends >= Starts
但是我想添加另一个逻辑约束:特定的警卫 (GuardID) 不能同时在两个地方,这意味着对于任何记录,由 Start/Ends 指定的时间段不应与为任何其他记录定义的时间段重叠由同一个警卫巡逻。
我可以想到两种方法来解决这个问题:
创建一个 INSTEAD OF INSERT 触发器。然后,此触发器将使用游标遍历 INSERTED 表,检查每条记录。如果任何记录与现有记录发生冲突,则会引发错误。这种方法的两个问题是:我不喜欢在现代版本的 SQL Server 中使用游标,而且我不确定如何为 UPDATE 实现相同的逻辑。 INSERTED 中记录的复杂性也可能相互冲突。
第二种似乎更好的方法是创建一个调用用户定义函数的 CONSTRAINT,传递 PatrolID、GuardID、Starts 和 Ends。然后,该函数将执行 WHERE EXISTS 查询,检查与 GuardID/Starts/Ends 参数重叠且不是原始 PatrolID 记录的任何记录。但是我不确定这种方法可能会产生什么潜在的副作用。
第二种方法更好吗?有没有人看到任何陷阱,例如一次插入/更新多行时(我担心的是因为该组中的行可能会发生冲突,这意味着它们“插入”的顺序会有所不同)。有没有更好的方法来做到这一点(比如一些花哨的 INDEX 技巧?)
【问题讨论】:
标签: sql-server sql-server-2005 validation triggers constraints