Удалить N самых старых записей в таблице

Как удалить N самых старых записей. Я ограничен Sybase. Мне нужно написать хранимую процедуру, которая будет принимать число X, а затем оставлять только X новых записей в таблице.

Например: Say ID автоматически увеличивается. Чем он меньше, тем старше эта запись.

ID  Text
=========
1   ASD
2   DSA
3   HJK
4   OIU

Мне нужна процедура, которая будет выполняться так.

execute CleanUp 2

и результат будет

ID  Text
=========
3   HJK
4   OIU

person Sergej Andrejev    schedule 28.04.2009    source источник


Ответы (4)


Примечание. Синтаксис SQL Server, но должен работать

Delete from TableName where ID in 
    (select top N ID from TableName order by ID )

Если вы хотите, чтобы N был параметром, вам нужно будет построить строку оператора и выполнить ее.

declare @query varchar(4000)
set @query = 'Delete from TableName where ID in '
set @query = @query + '(select top ' + @N + ' ID from TableName order by ID )'
exec sp_executesql @query
person Eduardo Molteni    schedule 28.04.2009
comment
Возможно, вы захотите, чтобы это было там, где ID НЕ находится - так как вы будете удалять первые N записей, а не удалять все, кроме первых n записей. - person Eric Petroelje; 28.04.2009
comment
Я думаю, что Сергей говорит, как удалить N самых старых записей. Я ошибаюсь? - person Eduardo Molteni; 28.04.2009
comment
К сожалению, это довольно медленно, но это, вероятно, единственное, что можно сделать. - person Sergej Andrejev; 29.04.2009
comment
Для повышения производительности я рекомендую вам получить самый высокий идентификатор между удаляемыми записями, а затем выполнить Удалить из TableName, где идентификатор ‹= @highestID - person Eduardo Molteni; 29.04.2009
comment
@Eduardo - Похоже, в заголовке указано n самых старых записей, но затем в описании говорится, что нужно оставить только X самых новых записей. Так что, думаю, мы оба правы :) - person Eric Petroelje; 29.04.2009
comment
Что не так с заголовком. Удалите N самых старых и оставьте X самых новых. X+N=Общее количество записей. После борьбы с проблемой производительности я в итоге воспользовался предложением Эдуардо. Я понимаю, что это не всегда достаточно точно, но производительность намного лучше. - person Sergej Andrejev; 30.04.2009

Мне больше всего нравится вариант Эдуардо, так как это самое простое решение, но, поскольку Сергей упоминает, что оно довольно медленное, вот альтернативное решение:

Создайте хранимую процедуру, которая выполняет следующие действия:

  1. Создайте временную таблицу с той же структурой, что и исходная таблица.
  2. Вставьте верхние N строк во временную таблицу.
  3. Сократите исходную таблицу.
  4. Скопируйте строки из временной таблицы обратно в исходную таблицу.

Как правило, это будет намного быстрее, особенно если у вас много строк в таблице.

person Eric Petroelje    schedule 29.04.2009

Если у вас есть кластеризованный индекс по идентификатору, безопасно выполнить удалить верхний запрос.

delete top 2 from TableName;
person brianegge    schedule 07.07.2009
comment
Нет, это действительно не так. Кластеризованный индекс не дает никаких гарантий упорядочения для любого оператора. Тот факт, что, по счастливой случайности, он работает в простых случаях, не означает, что на него следует полагаться. - person Damien_The_Unbeliever; 07.07.2009
comment
Из ранее связанного документа: когда вы используете top n с удалением, обновлением или в представлении, вы не можете указать порядок. Если в таблице есть подразумеваемый порядок из кластеризованного индекса, этот порядок применяется, в противном случае результаты непредсказуемы и могут быть в любом порядке. Я бы не сказал, что это везение, если это указано в документации. - person brianegge; 07.07.2009

Я знаю, что это старый вопрос, но это можно сделать без построения оператора, как говорится в верхнем ответе, с использованием CTE:

WITH MyCTE AS
(
    SELECT Field1, Field2, ROW_NUMBER() OVER (ORDER BY Field1 ASC) AS RowNum
    FROM MyTable
    WHERE Field2 = @WhatIWant
)
DELETE FROM MyCTE WHERE RowNum <= @NbRowsToDelete;
person Lionel Pire    schedule 31.03.2017