我研究并意识到我有一个独特的情况。
首先,由于我是新用户,因此我不允许将图片发布到主板上,因此请参阅下面的相应链接
我有多个表,其中列(不总是标识符列)按顺序编号,并且编号中不应有任何中断。我的目标是确保这一点保持正确。
沮丧和肮脏 我们有一个'事件'表,我们随机选择行的百分比并将行插入表'结果'。 “结果”中的“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)
示例表之前:
示例表格之后:
正如您所见,基于ID列从两个表中删除了2行。所以现在我要弄清楚如何重新编号item_ticket_id和item_void_id列,其中较高的数字减少到缺失值,下一个最高的数字减少,等等。问题#2,如果item_ticket_id发生变化,以便在ItemTickets中顺序, 然后 它必须在ItemVoid的item_ticket_id中更新该更改。
我感谢您对此提出的任何建议。
答案 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
然后你永远不必担心重新编号记录。这也使您能够返回并查看已删除的记录,并且不会丢失历史记录。
如果您确实要删除记录并对其重新编号,则可以通过以下方式执行此任务:
正如您所看到的,重新编号记录会涉及很多步骤。当你只能执行位标志的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将这些函数称为分析函数,它们支持更丰富的操作集。
我会强烈提醒您使用游标,因为这些游戏性能糟糕。当然,这不适用于标识列,因为无法修改此列。