使用唯一约束更新数据库记录

时间:2011-01-25 20:07:09

标签: sql sql-server sql-server-2008 sql-update unique-constraint

鉴于以下简单的表结构(SQL Server 2008),我希望能够保持数字序列列的唯一性,但我希望能够为任何给定的记录更新该值。

CREATE TABLE MYLIST(
      ID int NOT NULL IDENTITY(1, 1)
    , TITLE varchar(50) NOT NULL
    , SEQUENCE int NOT NULL
    , CONSTRAINT pk_mylist_id PRIMARY KEY(ID)
    , CONSTRAINT uq_mylist_sequence UNIQUE(SEQUENCE)
);

我的界面允许我混淆项目的顺序和我会在更新之前知道它们应该全部在中的非重叠序列,但是如何在不执行更新的情况下执行更新面对违反唯一约束的行为?

例如,假设我有这些记录:

ID  TITLE   SEQUENCE
1   APPLE   1
2   BANANA  2
3   CHERRY  3

我想将他们的序列号更新为以下内容:

ID  TITLE   SEQUENCE
1   APPLE   3
2   BANANA  1
3   CHERRY  2

但实际上我可以处理几十件物品。序列号不得重叠。我曾考虑尝试使用触发器或暂时禁用约束,但这似乎会产生更多问题。我正在使用C#和LINQ-to-SQL,但我们对严格的数据库解决方案持开放态度。

3 个答案:

答案 0 :(得分:3)

显而易见的方法是一批写。在内部,SQL将推迟约束检查,因此中间唯一性是无关紧要的。

逐行编写没有意义,导致问题。

您可以将其更改为写入临时表,然后在结尾处“刷新”结果,甚至首先检查临时表的唯一性。

DECLARE @NewSeq TABLE (ID int, NewSeq int)

INSERT @NewSeq (ID, NewSeq) VALUES (1, 3)
INSERT @NewSeq (ID, NewSeq) VALUES (2, 1)
INSERT @NewSeq (ID, NewSeq) VALUES (3, 2)

UPDATE
   M
SET
   SEQUENCE = NewSeq
FROM
   MYLIST M
   JOIN
   @NewSeq N ON M.ID = N.ID

答案 1 :(得分:2)

您可以为他们分配正确值的否定,然后在所有更新发生后,在您设置SEQUENCE = -SEQUENCE的位置进行最后更新。

效率非常高,但由于你说你只有几十件物品,我怀疑这种影响是否会引人注目。我还假设您可以使用负数作为“魔术值”来表示暂时错误分配的值。

答案 2 :(得分:0)

如果你真的必须遵循插入的工作流程而不知道正确的顺序,然后必须稍后再回来设置正确的顺序,我会说你最好的选择是摆脱唯一的约束,因为它会给你带来更多的问题而不是它的价值。当然,只有你知道这个独特的约束对你的应用程序有多大价值。