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

Sql 使用唯一约束更新数据库记录,sql,sql-server,sql-server-2008,sql-update,unique-constraint,Sql,Sql Server,Sql Server 2008,Sql Update,Unique Constraint,给定以下简单的表结构(SQLServer2008),我希望能够保持数字序列列的唯一性,但我希望能够为任何给定记录更新该值 我的界面允许我混淆项目的顺序,在进行更新之前,我会知道它们都应该在哪个不重叠的序列中,,但是我如何执行更新而不会遇到违反唯一约束的情况 例如,假设我有这些记录: ID TITLE SEQUENCE 1 APPLE 1 2 BANANA 2 3 CHERRY 3 我想将它们的序列号更新为: ID TITLE SEQUENCE 1 APPLE

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

我的界面允许我混淆项目的顺序,在进行更新之前,我会知道它们都应该在哪个不重叠的序列中,,但是我如何执行更新而不会遇到违反唯一约束的情况

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

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,但我对严格的数据库解决方案持开放态度。

显而易见的方法是作为一个批处理编写。在内部,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
您可以为它们指定正确值的负数,然后在所有更新发生后,在设置
SEQUENCE=-SEQUENCE
的位置执行最后一次更新


这不是很有效率,但既然你说你只有几十件物品,我怀疑其影响是否会明显。我还假设您可以使用负数作为“魔法值”来表示临时错误分配的值。

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

你能在一个声明中更新吗?如果回答了你的问题,我可以自由地尝试任何事情。我喜欢这样简单,并且在发布问题几分钟后,我自己也想到了这一点。对我来说,这可能是最有意义的。嗯。。。没有什么可以阻止某人直接在数据库中输入负数,这会破坏此解决方案。我确实知道更新之前的正确/所需顺序。对,但您不知道插入之前的正确顺序,对吗?我会知道所有记录的当前顺序和所需新顺序。我只是询问更新,而不是插入。但我很好奇,你对唯一约束的解释是,它们的值只能写入一次,永远不会更改吗?不是。我只是想澄清,在第一次插入记录之前,你不知道正确的值。因此,必须用错误的值插入它们,然后稍后您必须返回并进行更新。我不确定您为什么要询问插入,因为这超出了我的问题范围,但为了便于讨论,我会在现有序列的末尾插入新记录(例如,
MAX(sequence)+1
)。如果用户最后不想要它,他们可以移动它,我回到原来的问题。这似乎是技术上正确的解决方案,错误几率最小,尽管它需要额外的代码。就我而言,戴夫的负数技巧就足够了。
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