Как удалить первые 1000 строк из таблицы с помощью Sql Server 2008?

108

У меня есть таблица в SQL Server. Я хочу удалить из него первые 1000 строк. Однако я попробовал это, но вместо того, чтобы просто удалить первые 1000 строк, он удалил все строки в таблице.

Вот код:

delete from [mytab] 
select top 1000 
a1,a2,a3
from [mytab]
Эдгармце
источник
8
Вам нужен ORDER BY, чтобы сделать TOP значимым: см. Ответ @Martin Smith, который является единственным из пяти, которые имеют это. Иногда я отчаиваюсь
gbn
2
Вы хотите , чтобы удалить любые 1000 строк? Просто случайно выбран? Или, например, 1000 самых старых строк?
Ник Чаммас
13
Вы удалили всю таблицу, потому что delete from [mytab]это одно утверждение, а select top ...другое.
Ник Чаммас
2
Вам не нужно заказывать топ, все зависит от того, почему вы делаете ТОП. Если вам нужно удалить 10 миллионов строк и иметь 1 ГБ доступного места для журнала, используйте Delete TOP (10000) From dbo.myTable (с вашим предложением select) и продолжайте запускать его, пока не останется больше строк для удаления. Какая разница, если это произвольно. Сортировка только замедляет запрос.
tvanharp 06
1
Я понимаю, что это древний вопрос (за столько лет), но я думаю, что важно, чтобы люди прислушивались к комментариям @gbn . Хотя его комментарии не применимы к моей ситуации (попытка удалить блоки записей, не вызывая проблем с БЛОКИРОВКОЙ, но не заботясь о порядке их удаления), они, скорее всего, могут относиться к ВАШЕЙ ситуации. Обязательно учитывайте их, прежде чем слепо использовать приведенные ниже ответы, не содержащие предложения ORDER BY.
Эндрю Стейтц

Ответы:

196

Код, который вы пробовали, на самом деле состоит из двух утверждений. А, 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, прочтите следующее : «Строки, указанные в выражении TOP, используемом с INSERT, UPDATE, MERGE или DELETE, не расположены в каком-либо порядке».
Ник Чаммас
3
@ Магнус, да. Но не 2000 год. Возможно, в 2000 году можно будет использовать производную таблицу. У меня нет экземпляра для тестирования.
Мартин Смит
2
Я сделал немного другой способ (хотя я думаю, что CTE может быть лучше): УДАЛИТЬ T1 ИЗ (ВЫБРАТЬ TOP 1000 * ИЗ [MYTAB] ORDER BY A1) T1;
Abacus
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 Может быть, бесполезен для вас, но все же вопрос именно об этом.
Joachim Isaksson
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 Нет никаких условий относительно того, какие строки следует удалять, поэтому ORDER BY в подзапросе бесполезен
Олег Док
1
@gbn Вы упомянули WHERE в подзапросе - я фильтрую 1000 произвольных строк внутри выбранных критериев и затем удаляю. Действительный сценарий? Да. Если я добавлю ORDER BY NEWID () или что-то еще, это ничего не изменит - я все равно удаляю 1000 строк, отфильтрованных по выбранным критериям,
Олег Док
8
@gbn Если вы ищете допустимое использование TOP без ORDER BY: меня сюда привело то, что мне нужно удалить все строки, соответствующие некоторым критериям, но из соображений производительности я не хочу, чтобы он удалял более 10 000 строк вовремя. Мне все равно, какие строки он удаляет, так как я снова буду запускать команду через некоторый интервал, пока все такие строки не исчезнут.
Richiban
6
delete from [mytab]
where [mytab].primarykeyid in
(
select top 1000 primarykeyid
from [mytab]
)
Джейсон Дам
источник
4
Бесполезно: TOP без ORDER BY дает произвольные строки
gbn
4
@gbn Может быть, бесполезен для вас, но все же вопрос именно об этом.
Joachim Isaksson
3
@gbn Я не утверждал, что существует какой-либо порядок сортировки по умолчанию или что запрос хоть как-то полезен, я просто напомнил вам, что вопрос не задавал его, так что бы вы посоветовали упорядочить?
Joachim Isaksson
2
@gbn Я не знаю, почему вы так враждебны ко всем из-за того, что является отправной точкой. Я не утверждаю, что мой ответ - все, это просто предложение помочь кому-то. Я думаю, что важны ключи, которые возвращаются из подзапроса здесь.
Джейсон Дам
2
Это может быть все, что спрашивает. Я бы просто добавил примечание для других, читающих, чтобы подчеркнуть, что строки, удаленные таким оператором, не гарантируют, что они будут в каком-либо порядке.
Ник Чаммас
3
SET ROWCOUNT 1000;

DELETE FROM [MyTable] WHERE .....
Джо Борн
источник
2
Имеет ли это значение, имея дело всего с 1000 строками? Если бы это было 100000000 строк, тогда ваши баллы могли бы быть действительными, но только для 1000 строк это, безусловно, самое простое решение, предложенное до сих пор для SQL 2008.
Джо Борн
1

Это быстро. Попытайся:

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

Замените YourTABLEимя таблицы XXчислом, например 1000 pk- это имя поля первичного ключа вашей таблицы.

Хамед Элахи
источник
Фактически вы создаете две таблицы из одной, а затем удаляете места соединения. Это хорошо работает, когда вы хотите удалить самые старые (или самые новые) записи из таблицы, поскольку вы можете отсортировать их в первую очередь по возрастанию. Этот t-sql принят Microsoft (и это быстро).
Текила