SQL - 在删除后将顺序列重新编号为再次顺序

时间:2012-04-09 21:18:41

标签: sql

我研究并意识到我有一个独特的情况。

首先,由于我是新用户,因此我不允许将图片发布到主板上,因此请参阅下面的相应链接

我有多个表,其中列(不总是标识符列)按顺序编号,并且编号中不应有任何中断。我的目标是确保这一点保持正确。

沮丧和肮脏 我们有一个'事件'表,我们随机选择行的百分比并将行插入表'结果'。 “结果”中的“ID”列被传递给一堆删除查询。

这或多或少确保了几个表中缺少行。

我的问题: 找出一个sql查询,它将重新编号我指定的列。我宁愿不放弃专栏。

删除查询示例:

delete ItemVoid
from ItemTicket
join ItemVoid
on ItemTicket.item_ticket_id = itemvoid.item_ticket_id
where itemticket.ID in (select ID
            from results)

示例表之前:

enter image description here

示例表格之后:

enter image description here

正如您所见,基于ID列从两个表中删除了2行。所以现在我要弄清楚如何重新编号item_ticket_id和item_void_id列,其中较高的数字减少到缺失值,下一个最高的数字减少,等等。问题#2,如果item_ticket_id发生变化,以便在ItemTickets中顺序, 然后 它必须在ItemVoid的item_ticket_id中更新该更改。

我感谢您对此提出的任何建议。

3 个答案:

答案 0 :(得分:11)

(回答一个旧问题,因为这是我查看时的第一个搜索结果)
(MS T-SQL)

重新排序有间隙的ID列(不是Identity 1), 可以仅使用具有row_number()的简单CTE来执行以生成新序列。  UPDATE通过CTE'虚拟表'工作,没有任何额外的问题,实际上更新了基础原始表 不要担心在更新过程中ID字段发生冲突,如果你想知道当ID已经存在时会发生什么,它会  不会遇到这个问题 - 原始序列一次性改变为新序列。

WITH NewSequence AS
(
  SELECT
    ID, 
    ROW_NUMBER() OVER (ORDER BY ID) as ID_New
  FROM YourTable
)
UPDATE NewSequence  SET ID = ID_New;

答案 1 :(得分:3)

既然你正在寻找这方面的建议,我的建议是你需要重新设计这个,因为我看到你的设计存在很大的缺陷。

使用bit标记将记录标记为Inactive,而不是删除记录然后经历重新编号其余记录的麻烦。然后,当您查询记录时,只需包含一个WHERE子句,只包含活动的记录:

SELECT *
FROM yourTable
WHERE Inactive = 0

然后你永远不必担心重新编号记录。这也使您能够返回并查看已删除的记录,并且不会丢失历史记录。

如果您确实要删除记录并对其重新编号,则可以通过以下方式执行此任务:

  1. 创建新表
  2. 使用新号码
  3. 将原始数据插入新表格
  4. 放下旧桌子
  5. 使用更正的数字重命名新表
  6. 正如您所看到的,重新编号记录会涉及很多步骤。当你只能执行位标志的UPDATE时,你就会以这种方式创造更多的工作。

    您可以将DELETE查询更改为与此类似的内容:

    UPDATE ItemVoid
    SET InActive = 1
    FROM ItemVoid
    JOIN ItemTicket
        on ItemVoid.item_ticket_id = ItemTicket.item_ticket_id
    WHERE ItemTicket.ID IN (select ID from results)
    

    bit标志更容易,这将是我推荐的方法。

答案 2 :(得分:2)

您正在寻找的功能是窗口功能。在标准SQL(SQL Server,MySQL)中,函数是row_number()。您可以按如下方式使用它:

select row_number() over (partition by <col>)
from <table>

为了在您的情况下使用它,您将从表中删除行,然后使用with语句重新计算行号,然后使用更新分配它们。对于事务完整性,您可以将删除和更新包装到单个事务中。

Oracle支持类似的功能,但语法略有不同。 Oracle将这些函数称为分析函数,它们支持更丰富的操作集。

我会强烈提醒您使用游标,因为这些游戏性能糟糕。当然,这不适用于标识列,因为无法修改此列。