T-SQL修复行顺序/序列

时间:2016-09-07 14:21:12

标签: sql sql-server tsql stored-procedures sql-server-2012

概述:

我的应用程序中有一个页面,允许用户设置记录列表的优先级。这些记录基本上是团队需要完成的任务或目标。它们的给定顺序取决于用户将它们拖放到位。用户完成并保存更改后,它会循环访问数据并使用各自的订单更新数据库中的记录。

问题:

我现在遇到的问题是在一个单独的页面上,用户可以在该页面上删除可能分配了优先级的记录。由于优先级的保存和计算是在另一页上完成的,因此删除记录会导致序列中出现空白。

示例:

优先项目:

A (1)
B (2)
C (3)
D (4)
E (5)
F (6)
G (7)

项目从其他页面/功能中删除:

A (1)
B (2)
C (3)
D (4)
F (6)
G (7)

问题:

我需要制作一些类型的功能,我可以在删除记录后运行"修复/重新同步"这个数字序列。基本上,单个列priority需要更新,在示例中,F需要更新为5,G更新为6,以便修复序列间隙。

我尝试了什么:

大多数人正在研究解决这个问题的方法。我正在考虑将所有记录放入一个带有Auto Increment数字的临时表中,并使用它来更新优先级,但我觉得可能有一个更简单的解决方案并想要一些意见。

5 个答案:

答案 0 :(得分:1)

删除后,您只需更新大于刚刚删除的优先级的行。因此,如果您的列名称为Priority,并且您删除Priority = 5的行,则只需执行此类操作即可。请注意,您不需要在此处使用循环。

Update YourTable
set Priority = Priority - 1
where Priority > 5

答案 1 :(得分:1)

您可以使用触发器,它会在删除完成后自动触发。您始终可以从已删除的值中获取值。

更多信息

SQL Server ON DELETE Trigger

答案 2 :(得分:1)

正如其他人所建议的那样,如果您一次只删除一个,只需在删除后立即更新数字。如果您想立即重新编号整个表(可能有多个删除),您可以使用ROW_NUMBER()和CTE:

DECLARE @Project TABLE (
    Name nvarchar(100)
    , Priority int
);

-- Projects that are prioritized
INSERT @Project ( Name, Priority ) VALUES 
  ('A', 1)
, ('B', 2)
, ('C', 3)
, ('D', 4)
, ('E', 5)
, ('F', 6)
, ('G', 7)
;

SELECT * FROM @Project;

-- Projects get deleted
DELETE @Project WHERE Name = 'E';
DELETE @Project WHERE Name = 'C';

SELECT * FROM @Project;

-- Renumber
WITH P AS
(
    SELECT Name, Priority, ROW_NUMBER() OVER ( ORDER BY Priority ) AS NewPriority
    FROM @Project
)
UPDATE P SET Priority = NewPriority
;

-- Ta da!
SELECT * FROM @Project;

答案 3 :(得分:0)

为什么不在从数据库中提取记录的过程中设置优先级?这样你不需要改变优先级,因为它总是在你读取行时动态计算。唯一的问题是,当用户更改优先级序列后保存新序列时,将删除所有记录并以正确的顺序将其重新添加,并使用自动递增的主键(pk)。

我不知道你的序列,但这个例子应该给你一个想法。

Select Record,
  (Select count(*) From table 
   Where pk <= t.pk) Priority
From Table t

答案 4 :(得分:-1)

以下脚本可以为您提供一些见解

CREATE TABLE #Priority (
    Project VARCHAR(10) NOT NULL
    ,Ranking INT NOT NULL
)

INSERT INTO #Priority 
SELECT 'A',1 UNION
SELECT 'B',2 UNION
SELECT 'C',3 UNION
SELECT 'D',4 UNION
SELECT 'F',6 UNION
SELECT 'G',7 

SELECT
    Project
    ,RANK() OVER   
    (ORDER BY Ranking ASC) AS Ranking  
FROM
    #Priority