SQL存储过程:删除后重新排序行

时间:2012-07-16 23:51:48

标签: sql sql-server stored-procedures azure-sql-database sql-server-2012

在我的数据库中,我有三个表格如下:

  • Tasks (TaskID, TaskName, TaskDescription)
  • TaskDetails (TaskID, subTaskPosition, SubTaskID)
  • Subtasks (SubTaskID, Description)

我正在尝试编写Stored Procedure以完全删除SubTask,然后为SubTasks重新订购其他Task

注意事项:

  • TaskDetailsTasks链接到成分SubTasks
  • 可以在许多不同的任务中引用SubTask
  • Task应由SubTasks的有序列表组成......即1,2,3,4 NOT 1,3,4,5。

删除SubTask及其与Task的链接相当容易,如下所示:

  • DELETE FROM TaskDetails WHERE SubTaskID = @subTaskID
  • DELETE FROM SubTasks WHERE SubTaskID = @subTaskID

但是,在删除初始SubTasks后,我无法理解如何重新排序TaskDetails表格中的其他SubTask。在英语中,我需要执行以下操作 - “对于刚从中删除SubTask的所有任务,从已删除的行所用的所有subTaskPosition字段中减去1是”

任何帮助或指示赞赏...

戈登

3 个答案:

答案 0 :(得分:2)

我认为您必须为每项任务进行更新。这可以解决问题(语法适用于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

请注意,在从TaskDetails中删除之前执行此操作...并且您可能希望将所有内容都包装在事务中。

Gordon Edit - 我必须在更新代码中包含我的删除代码才能使其正常工作,否则(a)首先发生删除和“whereaskask = @subtaskID”没有返回任何内容OR(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

答案 1 :(得分:2)

这应该这样做:

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的更正版本:

;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)

抱歉延迟......

答案 2 :(得分:0)

首先获取子rask的位置,删除并更新记录:

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