如何在单个sql语句中组合更新和删除,而无需通过索引约束?

如何在单个sql语句中组合更新和删除,而无需通过索引约束?,sql,tsql,indexing,sql-server-2012,ado.net,Sql,Tsql,Indexing,Sql Server 2012,Ado.net,是否可以在不违反唯一索引约束的情况下执行以下sql语句,以确保位置是唯一的 UPDATE wl SET Position = Position - 1 FROM [dbo].[WatchList] wl WHERE Position > ( SELECT Position FROM [dbo].[WatchList] wl2 WHERE WatchListId = @WatchListID ); DELETE FROM [dbo].[WatchLi

是否可以在不违反唯一索引约束的情况下执行以下sql语句,以确保
位置是唯一的

UPDATE wl SET Position = Position - 1 
FROM [dbo].[WatchList] wl 
WHERE Position > ( SELECT Position FROM [dbo].[WatchList] wl2
                   WHERE WatchListId = @WatchListID );
DELETE FROM [dbo].[WatchList] WHERE WatchListID = @WatchListID
我想确保删除一条记录时不会出现职位空缺。所有位置较高的记录都应更新为
position=position-1

但这将导致唯一索引冲突,因为该行尚未删除。防止此问题的唯一方法是

  • 使用存储过程(如果可能,应避免使用,逻辑应为代码)
  • 要在删除记录之前确定旧位置,需要进行两次查询
更新:


谢谢你的努力。但是,由于没有简单的解决方法,我使用了第二种方法,因此首先确定旧位置,删除记录,然后更新跟随者。

如果位置是主键,为了导致索引冲突,您可以使用ALTER index并在删除后重新生成

DELETE FROM [dbo].[WatchList] WHERE WatchListID = @WatchListID
ALTER INDEX PK_Watchlist ON dbo.Watchlist REBUILD

但是您已经有两个查询了

declare @pos int;
set @pos = SELECT Position FROM [dbo].[WatchList] wl2
           WHERE WatchListId = @WatchListID;
DELETE FROM [dbo].[WatchList] WHERE pos = @pos;
UPDATE wl SET Position = Position - 1 
FROM [dbo].[WatchList] wl 
WHERE Position > @pos;

如果要运行两种不同的(类型的)语句,并在前后维护约束,请使用
MERGE

create table T (
    ID int not null,
    Position int not null,
    constraint PK_T_ID PRIMARY KEY (ID),
    constraint UQ_T_ID UNIQUE (Position))

insert into T(ID,Position) values
(12,1),
(22,2),
(36,3),
(47,4)


declare @ToDelete int
set @ToDelete = 22

;With Positions as (
    select
        Position
    from
        T
    where
        Position >= (select Position from T where ID = @ToDelete)
)
merge into T t
using (select Position from Positions) s
on
    t.Position = s.Position
when matched and ID = @ToDelete
then delete
when matched then update set Position = t.Position -1
;
select * from T
结果:

ID          Position
----------- -----------
12          1
36          2
47          3

如何处理同时删除记录的两个并发会话?不应出现缺口的要求背后的背景是什么?这是有效和安全的吗?我想这可能比在删除记录之前选择旧位置,然后在之后更新以下记录更有害。此外,位置不是主键,而是一列,必须为unqiue(实际上与另一列组合)。Update语句违反了此约束。啊。不,这不符合正常专栏,抱歉。谢谢。这似乎奏效了。但我实际上使用了第二种方法,它需要不止一个查询。首先确定旧位置,删除记录,然后更新追随者。可读性很重要:)@TimSchmelter—可能是最好的—直到输入是一个包含要应用的插入、更新和删除的表变量,并且您想在一个语句中展示这一切:-)