SQL存储过程:删除后对行重新排序
在我的数据库中,我有三个表,如下所示:SQL存储过程:删除后对行重新排序,sql,sql-server,stored-procedures,azure-sql-database,sql-server-2012,Sql,Sql Server,Stored Procedures,Azure Sql Database,Sql Server 2012,在我的数据库中,我有三个表,如下所示: 任务(任务ID、任务名称、任务描述) TaskDetails(TaskID、子taskPosition、子TaskID) 子任务(子任务,描述) 我正在尝试编写一个存储过程以完全删除子任务,然后为任务重新排序其他子任务 注意事项: 任务详细信息将任务链接到组成部分的子任务 子任务可以在许多不同的任务中引用 一个任务应该由一个有序的子任务列表组成。。。i、 e.1,2,3,4而不是1,3,4,5 删除子任务及其到任务的链接相当容易,如下所示: 从T
任务(任务ID、任务名称、任务描述)
TaskDetails(TaskID、子taskPosition、子TaskID)
子任务(子任务,描述)
存储过程
以完全删除子任务
,然后为任务
重新排序其他子任务
注意事项:
任务详细信息
将任务
链接到组成部分的子任务
子任务可以在许多不同的任务中引用
- 一个
任务
应该由一个有序的子任务列表
组成。。。i、 e.1,2,3,4而不是1,3,4,5
删除子任务及其到任务的链接相当容易,如下所示:
从TaskDetails中删除,其中SubTaskID=@SubTaskID
从子任务中删除,其中SubTaskID=@SubTaskID
但是,一旦删除了初始的子任务
,我无法理解如何重新排序任务详细信息
表中的其他子任务。在英语中,我需要执行以下操作-“对于刚刚从中删除了子任务的所有任务,从所有子任务位置
字段中减去1,该字段位于删除行之前所在的位置之后”
感谢您的帮助或指点
Gordon首先获取子光栅的位置,删除并更新记录:
declare @pos int
select @pos = subTaskPosition from TaskDetails where SubTaskID = @subTaskID
delete ...
delete ...
update TaskDetails set subTaskPosition = subTaskPosition + 1 where SubTaskID = @subTaskID and subTaskPosition > @pos
我想你必须为每项任务做一次更新。这样就可以了(语法适用于SQL Server):
请注意,在从TaskDetails中删除之前,请先执行此操作。。。您可能希望将所有内容都打包到事务中
Gordon Edit-我必须在更新代码中包含我的删除代码,否则(a)删除首先发生,并且“where subtaskID=@subtaskID”没有返回任何内容,或者(b)我在重新排序后进行了删除,并且重新排序(正确!)没有任何效果
DECLARE @TaskID uniqueidentifier
DECLARE @SubTaskPosition int
DECLARE curSubTaskPositionUpdate cursor fast_forward
FOR
SELECT TaskID, SubTaskPosition
FROM TaskDetails
WHERE SubTaskID = @subTaskID
OPEN curSubTaskPositionUpdate
FETCH NEXT FROM curSubTaskPositionUpdate INTO @TaskID, @SubTaskPosition
WHILE @@FETCH_STATUS = 0
BEGIN
-- Delete the subTask
DELETE FROM TaskDetails
WHERE TaskID = @TaskID
AND SubTaskPosition = @SubTaskPosition
-- Update the other subTasks
UPDATE TaskDetails
SET SubTaskPosition = SubTaskPosition - 1
WHERE TaskID = @TaskID
AND SubTaskPosition > @SubTaskPosition
FETCH NEXT FROM curSubTaskPositionUpdate INTO @TaskID, @SubTaskPosition
END
CLOSE curSubTaskPositionUpdate
DEALLOCATE curSubTaskPositionUpdate
这应该做到:
UPDATE TaskDetails
SET subTaskPosition = ROW_NUMBER() OVER(PARTITION BY TaskID ORDER BY subTaskPosition)
WHERE TaskID IN( SELECT s.TaskID
FROM TaskDetails s
WHERE SubTaskID = @subTaskID)
不需要循环。。。请注意,这也适用于同一任务缺少多个子任务或已删除多个子任务的情况
好的,下面是SQL Server的更正版本:
DECLARE @TaskID int
DECLARE @SubTaskPosition int
DECLARE curSubTaskPositionUpdate cursor fast_forward
FOR
SELECT TaskID, SubTaskPosition
FROM TaskDetails
WHERE SubTaskID = @SubTaskID
OPEN curSubTaskPositionUpdate
FETCH NEXT FROM curSubTaskPositionUpdate INTO @TaskID, @SubTaskPosition
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE TaskDetails
SET SubTaskPosition = SubTaskPosition - 1
WHERE TaskID = @TaskID
AND SubTaskPosition > @SubTaskPosition
FETCH NEXT FROM curSubTaskPositionUpdate INTO @TaskID, @SubTaskPosition
END
CLOSE curSubTaskPositionUpdate
DEALLOCATE curSubTaskPositionUpdate
;WITH
cteRows As
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY TaskID ORDER BY subTaskPosition) As NewPosition
FROM TaskDetails
)
UPDATE cteRows
SET subTaskPosition = NewPosition
WHERE TaskID IN( SELECT s.TaskID
FROM TaskDetails s
WHERE SubTaskID = @subTaskID)
抱歉耽搁了…这是什么SQL类型的?Oracle,MS SQL Server?DB2?MySql?对不起,我应该说-MS SQL Server(2012)-尽管它也需要在Azure SQL上运行!感谢下面的回复-我稍后会尝试一下,让你知道我的进展如何。非常感谢!我喜欢!应该注意的是,它可能会更新不需要更新的行。另外,我认为应该是“WHERE TaskID IN”(“.这是一个值子查询,它与IN或EXISTS子查询同样有效(而且它们通常(但不总是)可互换)。嗨,Barry,非常感谢您的帮助。这可能是因为我没有指定我使用的是SQL Server,但我在读取时出错了“窗口函数只能出现在SELECT或ORDER BY子句中。”。有什么想法吗?非常感谢Barry-虽然这项看似简单的工作实际上相当繁重。不幸的是,您的代码在我的应用程序中不起作用。我认为原因是因为我必须在重新排序代码之前从TaskDetails表中删除子任务,所以您的”其中SubTaskID=@SubTaskID“找不到任何东西。如果你想看的话,我已经设法让下面的James代码版本正常工作了-尽管我相信你几乎有了一个更优雅的解决方案。再次感谢。感谢James,通过一些小的调整,我成功地使这个工作正常-尽管如果我可以调整的话,Barry的代码可能会更有效!