如何在单个sql语句中组合更新和删除,而无需通过索引约束?
是否可以在不违反唯一索引约束的情况下执行以下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
位置是唯一的
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—可能是最好的—直到输入是一个包含要应用的插入、更新和删除的表变量,并且您想在一个语句中展示这一切:-)