如何在截断并保留 ID 列值后从临时表中重新插入记录

Posted

技术标签:

【中文标题】如何在截断并保留 ID 列值后从临时表中重新插入记录【英文标题】:How to re-insert records from temporary table after truncate and keep ID column values 【发布时间】:2014-03-10 00:50:21 【问题描述】:

假设我想删除 SQL Server 表中三个月前插入的所有记录,并保留此后插入的记录。我们正在处理三个月期间两边的许多记录,所以我决定不使用 WHERE 子句语句运行 DELETE,而是将所有内容插入临时表,截断原始表,然后插入临时表中的所有记录回到原来的表。

但我想保留主键 ID 列中的所有值,这些值由另一个表中的外键使用。如何避免重置种子值以及插入每条记录的 ID 列相同的所有内容?

【问题讨论】:

不要删除...不要删除。在该范围内添加“活动”标志或其他内容以将记录标记为活动或已删除。 我正在删除,以便我们可以释放数据库中的空间。 Boss 不想为持有 2000 万条客户很少查看的广告印象日志而付费。因此,我将 3 个月以上的所有内容插入到一个表格中,该表格包含每个广告的总展示次数和点击次数。应该在服务器上释放几 GB。 如果你从另一个表中引用这个表,你是否也删除了对旧行的引用? 没有对该表的引用 【参考方案1】:

删除外键并禁用原始表中的标识增量。然后执行您提到的上述过程。那是

    将记录插入临时表 - (插入 - 选择您想要的任何内容以及另一个表中存在的外键行)。 截断原始表。 将临时表中的记录插入原表(如果记录很多,删除原表并将临时表重命名为原表名)。 添加外键约束并启用标识属性 重新设定身份。 - DBCC CHECKIDENT (yourtable, reseed, 10045)

10045 - 对应于临时表中的行数。所以身份种子从 10046 开始。

希望这会有所帮助。

【讨论】:

我从CHECKIDENT得到的身份种子会得到临时表的行数还是得到最新的ID列值?我需要新种子是 ID 列中的最大值而不是行数。 您将种子值传递给CHECKIDENT 函数。您可以在插入后从表中选择MAX 标识值,然后将其传递给CHECKIDENT 以获得所需的功能。【参考方案2】:

试试:

SET IDENTITY_INSERT OLD_TABLE ON;
GO
INSERT INTO OLD_TABLE ( ... columns, including ID ... )  
     SELECT ( ... columns, including ID ... )  FROM TEMP_TABLE;

【讨论】:

以上是关于如何在截断并保留 ID 列值后从临时表中重新插入记录的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SQL 中对触发器进行语法化,以便在插入后从同一个表中更新列(oracle 数据库)

使用 SQL Server DTS 包有条件地在目标表中插入/更新行

如果列值 id 与另一个表中的 ID 描述匹配,则在指定列中插入数据(规范化形式)

动态插入语句需要返回插入的ID

在使用表中的连接列值填充列表框时,如何检索相应的 ID 并传递值 onchange [关闭]

在 Redshift 中插入列的子字符串