2012-04-09 74 views
3

我研究并意识到我有一个独特的情况。SQL - 删除一个顺序列后重新编号为

首先,我不允许张贴尚未图像板,因为我是一个新用户,所以看到合适的链接下面

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

Down and Dirty 我们有一个'Event'表,我们随机选择一行的百分比并将行插入表'Results'中。 “结果”中的“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列。所以现在我要弄清楚如何对item_ticket_id和item_void_id列进行重新编号,其中较高的数字会减少到缺失的数值,而下一个最高的数字会减少,等等。问题#2,如果item_ticket_id更改为顺序在ItemTickets中,然后 它必须更新ItemVoid的item_ticket_id中的更改。

我很欣赏你可以给予的任何建议。

+7

IMO这似乎是一个设计缺陷,而不是删除行,使用位标记标记为非活动,然后被排除在您的查询。然后,在每次删除之后,您不需要重新编号记录。 – Taryn 2012-04-09 21:21:45

回答

3

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

而不是删除记录,然后通过重新编号其余记录的麻烦,使用bit标志将标记记录为Inactive。然后,当你正在查询的记录,只包括WHERE子句仅包括记录是积极的:

SELECT * 
FROM yourTable 
WHERE Inactive = 0 

那么你从来不必担心重新编号的记录。这也使您能够返回并查看将被删除的记录,并且不会丢失历史记录。

如果你真的要删除的记录,并重新编号他们,那么你可以执行此任务的方式如下:

  1. 创建新表
  2. 使用新号码时插入自己的原始数据到新表
  3. 删除旧表
  4. 与该修正的数字命名新表

一你可以看到重新编号记录需要很多步骤。当您只能执行位标志的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

您正在查找的功能是窗口功能。在标准的SQL(SQL Server,MySQL)中,函数是row_number()。

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

为了你的情况来使用这个,你会从表中删除的行,然后使用with语句重新计算行数,然后使用更新为它们分配:您按如下方式使用它。对于事务完整性,您可能会将删除和更新包装到单个事务中。

Oracle支持类似的功能,但语法稍有不同。 Oracle将这些功能称为分析功能,并支持对其进行更丰富的操作。

我强烈建议您不要使用游标,因为这些游戏表现糟糕。当然,这不适用于标识列,因为这样的列不能被修改。

+0

你好Gordon,你有没有使用WITH命令的例子,你不需要为我做这个工作,我只需要一个通用的例子。作为最后的手段,选项2是,我将对行重新编号以确保顺序编号的完整性,而不管新的ID编号是否在新的一行数据中。 – user1322659 2012-04-10 03:06:12

11

(回答一个老问题,因为它的时候我一直在寻找这样了第一个搜索结果)
(MS T-SQL)

要重新排序的ID列(不为单位一个)有空位, 可以使用只有一个简单的CTE与row_number()来执行,以生成一个新的序列。 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; 
+0

这似乎工作 – 2015-05-25 12:12:38

+0

太棒了!对于那些使用此查询的人,请记住添加一个WHERE以仅影响表中的某些行。 – JC203 2017-04-05 14:47:42