如何在没有数据丢失的情况下删除SQL Server中的大量数据?

问题描述 投票:2回答:2

我一直在处理日常过程中数百万的数据删除。

基本上我有4张桌子。

Table_A
Table_B
Table_C
Table_D

我试图在所有表中删除超过10天的数据。

可能我会在每张表中删除大约一百万。我已经创建了一个存储过程来执行这些操作。

我删除数据的步骤是

步骤1:将最近几天(我必须保留的数据)移动到临时表

select * into Table_A_Temp
from Table_A
where <<where clause last 10 days to till date>>

第2步:将主表重命名为旧表(包含所有日期数据的表)

exec sp_rename 'Table_A', 'Table_A_Old'

步骤3:将临时表重命名为主表(包含最后几天到日期之间数据的表)

exec sp_rename 'Table_A_temp', 'Table_A'

步骤4:如果在复制过程中插入了任何新数据,则使用时间帧查询临时表

Insert into Table_A
select * from Table_A_old

第5步:删除旧表

DROP TABLE Table_A_old

第6步:在主表中创建键和约束(表示重命名的表)

code to create primary keys and constraints

问题:

如果我在存储过程运行时不断地将数据插入表中,我将丢失数据几秒钟。

案例1:重命名表时

当我将main和temp表重命名为main时

我收到无效对象错误(该表存在错误)

案例2:我的两个表有外键关系

如果我在创建约束和键之前插入数据我会收到相关错误。

如何在不丢失数据的情况下正确处理和删除数据。

请提供最佳实践建议。

sql sql-server performance sql-server-2012 sql-delete
2个回答
1
投票

为了避免丢失数据,我只删除它们所在的记录而不是创建/重命名表。 SQL Server将为您处理插入和删除以防止数据丢失。有几种方法可以做到这一点,下面是一个建议。

步骤1:获取要删除的行的ID /标识符,并将它们存储在临时表中。

SELECT Id 
INTO #TEMP_Table_A_RowsToDelete
FROM Table_A
WHERE <<your_date_column <= 10 days ago>>

然后,您将拥有一个临时表#TEMP_Table_A_RowsToDelete,其中包含您要删除的行的Id值。

步骤2(可选):使用此表删除引用表中的任何相关数据(如果存在)。

DELETE t1
FROM ForeignKeyTable t1
INNER JOIN #TEMP_Table_A_RowsToDelete t2
  ON t1.[ForeignKeyColumn] = t2.Id

这将删除链接到主表上主键的表中的所有相关数据。您将对所有链接表重复此操作,以确保外键约束不会阻止您删除父表中的行。

第3步:从主表中删除行。

DELETE t1
FROM Table_A t1
INNER JOIN #TEMP_Table_A_RowsToDelete t2
  ON t1.[Id] = t2.Id

这将根据您在步骤1中添加到临时表中的内容删除超过10天的行。如果您在步骤2中删除了所有相关数据,则不会导致问题。

您需要为列表中的每个表重复上述步骤。


1
投票

据推测,这是一个持续的需求。

你应该做的是分区表。存在的地方是了解documentation中的分区。

可能最简单的方法如下:

  • 将每个表复制到一个新位置。
  • 重新定义每个表并添加分区功能。
  • 将数据加载回表中。

第三步,只需加载您想要的最新数据。

然后,在将来,您可以每天简单地删除最旧的分区。您可以设置SQL Server代理作业来执行此操作,系统将自动运行。

© www.soinside.com 2019 - 2024. All rights reserved.