如何使用Sql Server 2008从表中删除前1000行?


108

我在SQL Server中有一张表。我想从中删除前1000行。但是,我尝试了此操作,但我不仅仅是删除了前1000行,而是删除了表中的所有行。

这是代码:

delete from [mytab] 
select top 1000 
a1,a2,a3
from [mytab]

8
你需要一个ORDER BY,使TOP有意义的:@马丁看到史密斯的回答这是唯一的五到有这一个。有时我感到绝望
gbn 2012年

2
您要删除任何 1000行吗?只是随机选择的?或者,例如,最古老的1000行?
Nick Chammas 2012年

13
您删除了所有表,因为它delete from [mytab]是一个语句,而select top ...另一个语句。
Nick Chammas 2012年

2
您不需要订购顶部,这取决于您为什么要做顶部。如果需要删除1000万行并具有1 GB的可用日志空间,请使用dbo.myTable中的Delete TOP(10000)(带有select子句)并继续运行它,直到没有要删除的行为止。谁在乎它是否武断。排序只会减慢查询速度。
tvanharp

1
我意识到这是一个古老的问题(在SO年中),但我确实认为人们考虑@gbn的评论很重要。尽管他的评论不适用于我的给定情况(试图删除记录块而不会引起LOCK问题,但实际上并不关心删除它们的顺序),但它们很可能适用于您的情况。确保在盲目利用下面不包含ORDER BY子句的答案之前考虑它们。
安德鲁·斯蒂兹

Answers:


196

您尝试的代码实际上是两个语句。A DELETE后跟一个SELECT

您未按内容定义TOP顺序。

对于特定的排序标准,从CTE或类似表表达式中删除是最有效的方法。

;WITH CTE AS
(
SELECT TOP 1000 *
FROM [mytab]
ORDER BY a1
)
DELETE FROM CTE

13
对于那些想知道为什么不能这样做的人DELETE TOP (1000) FROM table ORDER BY column,请阅读以下内容:“与INSERT,UPDATE,MERGE或DELETE一起使用的TOP表达式中引用的行未按任何顺序排列。”
Nick Chammas

3
@Magnus是的。不是2000。在2000年可能有可能使用派生表。我周围没有实例可以测试。
马丁史密斯


2
我做了一个稍微不同的方法(尽管我认为CTE可能更好看):删除T1 FROM(选择TOP 1000 * FROM [MYTAB] ORDER BY A1)T1;
算盘

4
@Liam-只是因为如果在CTE之前有任何先前的声明,则需要以分号终止,因此将其附加到WITH尚未这样做的人的先发制人投诉中。
马丁·史密斯

86

对于sql2005 +可能更好用:

DELETE TOP (1000)
FROM [MyTab]
WHERE YourConditions

对于Sql2000:

DELETE FROM [MyTab]
WHERE YourIdField IN 
(
  SELECT TOP 1000 
    YourIdField 
  FROM [MyTab]
  WHERE YourConditions
)

如果要删除行的特定子集而不是任意子集,则应显式指定子查询的顺序:

DELETE FROM [MyTab]
WHERE YourIdField IN 
(
  SELECT TOP 1000 
    YourIdField 
  FROM [MyTab]
  WHERE YourConditions
  ORDER BY ExplicitSortOrder
)

感谢tp @gbn提及并要求提供更清晰准确的答案。


3
@gbn可能对您没有用,但这仍然是问题的所在。
约阿希姆·伊萨克森

1
@Joachim Isaksson:继续阅读有关TOP的内容,然后回来。没有在集合中没有ORDER BY的TOP之类的东西。或者,去找我一个能证明我错误的规范参考...为了节省您的搜索,sqlblog.com / blogs / alexander_kuznetsov / archive / 2009/05/20 /…blogs.technet.com/b/wardpond/archive /
2007/07/19

1
@gbn没有关于要删除的WHICH行的任何条件,因此子查询中的ORDER BY没用
Oleg Dok 2012年

1
@gbn您是否在子查询中提到WHERE-我在所选条件中过滤了1000条任意行,然后将其删除。有效方案?是。如果我添加ORDER BY NEWID()或它什么都没有改变-我仍会删除按选定条件过滤的1000行
Oleg Dok 2012年

8
@gbn如果您正在寻找不带ORDER BY的TOP的有效使用:带给我的是这里我需要删除所有符合某些条件的行,但是出于性能原因,我不希望它删除超过10,000行一次。我不在乎它会删除哪些行,因为我将每隔一段时间再次运行命令,直到所有这些行都消失了。
Richiban 2014年


6
delete from [mytab]
where [mytab].primarykeyid in
(
select top 1000 primarykeyid
from [mytab]
)

4
没用:没有ORDER BY的TOP给出任意行
gbn 2012年

4
@gbn可能对您没有用,但这仍然是问题的所在。
约阿希姆·伊萨克森

3
@gbn我不是说有默认的排序顺序,也不是查询有任何用处,我只是想提醒您,这个问题并没有要求,那么您建议按什么顺序排序?
约阿希姆·伊萨克森

2
@gbn我不知道为什么你对所有人如此敌视,这是一个起点。我并不是说我的答案就是全部,它仅仅是帮助别人的建议。我认为重要性是从子查询返回的键。
杰森·达姆

2
这可能就是问询者所寻找的全部。我只是为其他阅读者添加注释,以强调这样的语句删除的行不能保证以任何顺序排列。
Nick Chammas 2012年

3
SET ROWCOUNT 1000;

DELETE FROM [MyTable] WHERE .....

2
当只处理1000行时,真的重要吗?如果是亿行那么你的焦点可能是有效的,但只是1000行,这是迄今为止提出的迄今2008年SQL最简单的解决方案
乔·伯恩

1

很快 试试吧:

DELETE FROM YourTABLE
FROM (SELECT TOP XX PK FROM YourTABLE) tbl
WHERE YourTABLE.PK = tbl.PK

YourTABLE表名称(XX例如1000) 替换为表 pk的主键字段的名称。


您实际上是从一个表创建两个表,然后在连接的地方删除它们。当您想从表中删除最早(或最新)的记录时,它可以很好地工作,因为您可以对它们进行升序排列。该t-sql已被Microsoft接受(并且速度很快)。
龙舌兰酒
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.