我需要从一个有大约600万行的表中删除大约500万行,因为我没有磁盘空间。有没有快速删除它们的方法?我试过在批处理上调用delete,但是运行需要很长时间,有时它会因为锁而抛出错误而且什么都不做。
编辑:
我正在进行类似
的查询delete from <table> where updated_timestamp < '2012-02-20'
现在,为了获得更小的批次,查询如下
delete from <table> where id < [100000 row increments]
我得到的错误是它无法锁定表格。我目前没有确切的文字,但是如果我再次遇到它,我会把它粘贴在这里
答案 0 :(得分:2)
删除行的唯一方法是DELETE FROM <table> WHERE <some condition>
,或删除TRUNCATE TABLE <table>
或DROP TABLE <table>
的所有行(然后重新创建)。
我没有提供任何可以提供更具体答案的信息,我担心。您可以使用WHERE
子句中的条件在较小的行集(批处理)中执行此操作。 (“有时会抛出错误”对帮助你解决它没有用,顺便说一下,因为“抛出错误”没有关于“错误”可能是什么的信息是没有意义的。)
答案 1 :(得分:1)
我的建议是在您的情况下选择要保留在一个可靠的“临时”表中的百万条记录,然后截断表格,因为当您删除记录时,它会将您删除的所有记录记录到日志中额外的磁盘空间。截断表后,将实体“temp”表中的记录添加回原始表中,并删除实体“temp”表。
您可以做的其他事情是在数据库上运行CHECKPOINT
,然后将其缩小。它应该释放磁盘上的一些空间。
答案 2 :(得分:0)
前两个答案绝对正确,你应该相信它。
您正在寻找的是以下
SELECT * INTO into #temp FROM <table> WHERE updated_timestamp >= '2012-02-20'
TRUNCATE TABLE <table>
INSERT INTO <table> SELECT * FROM #temp
如果你(a)有引用表的外键,或者(b)有标识列,这会变得有点复杂。对于前者,您需要通过外键约束删除引用表中记录的所有记录,删除约束,然后截断并重新创建外键。对于后者,您可以使用以下内容作为insert语句:
SET IDENTITY INSERT <table> ON
INSERT INTO <table> (<field_list>)
SELECT <field_list>) FROM #temp
SET IDENTITY INSERT <table> ON
答案 3 :(得分:0)
以下是删除日志表的代码,其中日志超过一年。批处理循环。
declare @batch int
declare @i int
declare @j int
set @batch = 1000
set @j = (select (COUNT(*)/@batch) + 1 from LOG_TABLE
where ACCESS_DATE < dateadd(year,-1,getdate()))
set @i = 0
print @j
while (@i < @j)
BEGIN
delete top (@batch)
from LOG_TABLE
where ACCESS_DATE < dateadd(year,-1,getdate())
SET @i = @i + 1
END