SQL Server 事务处理期间禁用约束

e5nqia27  于 2023-01-01  发布在  其他
关注(0)|答案(3)|浏览(122)

我正在整理一个表,该表将用于向某些信息请求发送跟进消息。请求将发送给一组人,并跟踪响应。如果某个人未响应,则可能会发送零个或多个跟进消息。我创建了一个表:

FollowupId int primary key, 
RequestId int foreign key (outside this example), 
Follows int foreign key (FollowupId), 
Message varchar

如果一条消息是第一条后续消息,Follows将为null,否则,它是其他一些后续消息的id,我还在Follows上添加了一个唯一的约束,也就是说,不能有一条以上的消息跟随任何给定的消息。
编辑:我还应该突出显示Follows上的外键。它引用了这个表中的FollowupId。因此,如果A-〉B-〉C,仅仅删除B就会使C中的外键无效。类似地,仅仅更新C以跟随A是不可能的,因为B已经跟随A,并且唯一约束禁止复制。
当然,问题是,如果该消息后面跟着另一个消息,则删除后续条目现在很困难。在我看来,应该可以禁用约束检查,以便可以删除中间的后续消息,“上移”后续的后续消息,然后重新启用检查。是否有某种方法可以仅在事务的持续时间禁用约束?
(Also,我意识到在这个表中使用RequestId可能会导致数据不一致。使用Followups [FollowupId,Message]、InitialFollowups [FollowupId,RequestId]和FollowingFollowups [FollowupId,Follows]表可能会更好。不过我认为这不必要地使这个示例复杂化。)

dbf7pr2w

dbf7pr2w1#

为某些修改禁用/启用约束通常不是一个好主意,而且性能可能会很差。无论何时执行此操作,请确保您的约束不仅是启用的,而且在完成后是受信任的。
在您的情况下,您需要删除一行并修改另一行。如果您已经使用SQL 2008,则应该使用MERGE,这样可以在一个命令中同时执行删除和更新操作。

qaxu7uf2

qaxu7uf22#

我发现(至少在SQL Server上)禁用唯一约束是不可能的。可以禁用外键约束,将要删除的记录的id设置为无效和不可能的id(例如在我的例子中为-1),更改跟踪id,删除有问题的记录,然后恢复约束检查。假设以下数据:

FollowId | RequestId | Follows | Message  
--------------------------------------------------------------------
       1 |        17 |    NULL | "First one"  
       2 |        17 |       1 | "Second one, delete this one"  
       3 |        17 |       3 | "Third one, but make it the second"

我使用了以下策略:

BEGIN TRANSACTION;

ALTER TABLE RequestFollowups NOCHECK CONSTRAINT FK_Follows_FollowId;

UPDATE      RequestFollowups SET Follows = -1 WHERE FollowupId = 2;
UPDATE      RequestFollowUps SET Follows =  1 WHERE FollowupId = 3;
DELETE FROM RequestFollowups                  WHERE FollowupId = 2;

ALTER TABLE RequestFollowups WITH CHECK CHECK CONSTRAINT FK_Follows_FollowId;

COMMIT TRANSACTION;

(Note倒数第二行is intentional and not a typo上的CHECK CHECK。)

kdfy810k

kdfy810k3#

首先更新其他值,然后执行删除操作。
所以如果顺序是
A → B → C
你要删除B,更新C的Follows到A,A的FollowedUp到C,然后删除B。

相关问题