Як видалити перші 1000 рядків із таблиці за допомогою Sql Server 2008?


108

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

Ось код:

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

8
Вам потрібна ЗАМОВЛЕННЯ, щоб зробити ТОП значимим: див. Відповідь @Martin Smith, яка є єдиною з п'яти, яка має це. Я іноді
впадаю у

2
Ви хочете , щоб видалити будь-які тисячі рядків? Просто вибрано випадковим чином? Або, наприклад, топ-1000 найстаріших рядків?
Нік Чаммас

13
Ви видалили всю таблицю, оскільки delete from [mytab]це одне твердження, а select top ...інше -.
Нік Чаммас

2
Вам не потрібно замовляти топ, залежно від того, чому ви робите TOP. Якщо вам потрібно видалити 10 мільйонів рядків та мати 1 ГБ місця журналу, скористайтеся Видалити TOP (10000) З dbo.myTable (із вибраним пунктом) та продовжуйте працювати, поки не буде більше рядків для видалення. Кому байдуже, якщо це довільно. Сортування лише уповільнює запит.
tvanharp

1
Я усвідомлюю, що це давнє питання (в ЗО років), але я думаю, що важливо, щоб люди розглядали коментарі @gbn . Хоча його коментарі не стосуються моєї даної ситуації (намагаючись видалити блоки записів, не викликаючи проблем LOCK, але насправді не піклуючись про порядок їх видалення), вони, ймовірно, можуть стосуватися ВАШОЇ ситуації. Переконайтесь, що ви їх врахували, перш ніж сліпо використовувати відповіді нижче, які не містять пункт ЗАМОВИТИ ЗА.
Ендрю Штайц

Відповіді:


196

Код, який ви спробували, насправді два твердження. А DELETEза ним a 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
@Magnus так. Не 2000, хоча. Можливо, можна використати похідну таблицю в 2000 році. Я не мав примірника для тестування.
Мартін Сміт


2
Я зробив дещо інший спосіб (хоча я думаю, що CTE може бути приємніше дивитись): ВИДАЛИТИ T1 ВІД (ВИБІР ТОП 1000 * З [MYTAB] ЗАМОВЛЕННЯ А1) 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, а потім поверніться. Не існує такої речі, як TOP без ЗАМОВЛЕННЯ В наборах. З іншого боку , піти і знайти мені канонічну посилання , яка доводить мене неправильно ... Для того, щоб зберегти ви шукаєте, sqlblog.com/blogs/alexander_kuznetsov/archive/2009/05/20 / ... і blogs.technet.com/b/wardpond/archive /
2007/07/19

1
@gbn Немає жодних умов щодо видалення рядків, тому ЗАМОВИТИ В підзапиті марно
Олег Док

1
@gbn Ви згадали, де в підзапиті - Я фільтрую 1000 довільних рядків всередині обраних критеріїв і видаляю потім. Дійсний сценарій? Так. Якщо я додам ЗАМОВЛЕННЯ NEWID () або все, що нічого не змінить - я все одно видаляю 1000 рядків, відфільтрованих за обраними критеріями
Олег Док

8
@gbn У випадку, якщо ви шукаєте дійсне використання ТОП без ЗАМОВЛЕННЯ ПО: що мене тут привело, мені потрібно видалити всі рядки, що відповідають деяким критеріям, але, з міркувань продуктивності, я не хочу, щоб він видаляв більше 10 000 рядків зараз. Мені все одно, які рядки вона видаляє, оскільки я знову запускатиму команду через деякий проміжок часу, поки всі такі рядки не зникнуть.
Річібан


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

4
Марно: TOP без
ПОРЯДОКУ

4
@gbn Можливо, марний для вас, але все-таки саме це питання задається.
Йоахім Ісакссон

3
@gbn Я не стверджував, що існує який-небудь порядок сортування за замовчуванням або що запит навіть будь-яким чином корисний, я просто нагадав вам, що в цьому питанні не задавали жодного питання, а що б ви запропонували замовити?
Йоахім Ісакссон

2
@gbn Я не знаю, чому ти так вороже ставишся до кожного через щось, що є відправною точкою. Я не стверджую, що моя відповідь - це кінець, це лише пропозиція допомогти комусь. Я думаю, що важливе значення мають ключі, які повертаються з підзапиту.
Гребля Джейсона

2
Це може бути все, що шукає запитувач. Я просто додав би примітку для інших, хто читає, наголошуючи, що рядки, видалені таким висловлюванням, не гарантуються в будь-якому порядку.
Нік Чаммас

3
SET ROWCOUNT 1000;

DELETE FROM [MyTable] WHERE .....

2
Чи маєте справу лише з 1000 рядками, чи справді це має значення ?? Якби це було 100 000 000 рядків, то ваші очки могли б бути дійсними, але всього лише 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 прийнятий корпорацією Майкрософт (і це швидко).
Текіла
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.