Bulk DELETE на SQL Server 2008 (Есть ли что-нибудь вроде Bulk Copy (bcp) для удаления данных?)

Есть ли какое-либо решение для массового удаления в SQL Server?

Я не могу использовать TRUNCATE, потому что я хочу использовать WHERE для ограничения строк в действии.

Есть ли что-нибудь вроде Bulk Copy (bcp) для удаления данных?

Ответы

Ответ 1

Нет.

Вы хотите DELETE с предложением WHERE: это стандартный SQL.

Что вы можете сделать, так это пакетное удаление:

SELECT 'Starting' --sets @@ROWCOUNT
WHILE @@ROWCOUNT <> 0
    DELETE TOP (xxx) MyTable WHERE ...

Или если вы хотите удалить очень высокий процент строк...

SELECT col1, col2, ... INTO #Holdingtable
           FROM MyTable WHERE ..opposite condition..
TRUNCATE TABLE MyTable
INSERT MyTable (col1, col2, ...)
           SELECT col1, col2, ... FROM #Holdingtable

Ответ 2

Вы можете сделать пару вещей, если хотите удалить часть своей таблицы, а не TRUNCATE.

вы можете выбрать часть таблицы в новую таблицу, а затем переключить два так:

SELECT *
INTO tmp_MyTable
FROM MyTable
WHERE Key='Value'

IF @@ROWCOUNT > 0
BEGIN
    EXEC sp_rename MyTable, old_MyTable, NULL
    EXEC sp_rename tmp_MyTable, MyTable, NULL
    TRUNCATE old_MyTable 
END

Во-вторых, если вы используете Partitioning, вы можете создать идентичную (пустую) таблицу на той же схеме разделов.. и если таблица разделена в соответствии с вашей логикой архивирования/очистки, вы можете переместить один блок раздела из своего главной таблицы в новую таблицу, а затем усечь новую таблицу. Например:

ALTER TABLE MyTable
SWITCH PARTITION 15 TO purge_MyTable PARTITION 2 
GO; 

TRUNCATE TABLE purge_MyTable 

Ps. Разделы доступны в SQL 2005/08 Ent.

Надеюсь, это поможет!

Ответ 3

Sychare Jedko,

Преимущество TRUNCATE заключается в том, чтобы избежать регистрации каждого отдельного удаления в файле журнала. оператор TRUNCATE создаст единую запись (в журнале) для всей партии.

Ответ 4

Просто столкнулся с подобной проблемой, работая над промежуточной таблицей, у которой были проблемы с масштабированием с правильными блокировками.

Поскольку соответствующая таблица упоминается только в одном месте для нас, мы просто заменили эту ссылку запросом для имени динамической таблицы, которое создается с помощью "select into", аналогичного тому, что предлагалось gbn.

Это поддерживается, поскольку промежуточная таблица упоминается только в одном месте в коде, а расход дополнительного вызова базы данных вместе с созданием таблицы оправдан в контексте складирования. Если у вас всего несколько сотен записей или многократно ссылаются на таблицу в вашем коде, тогда этот подход может не работать.

Ответ 5

При обработке миллиона строк я предпочитаю иметь инструкцию WHERE и использовать SELECT INTO в таблице копирования, удалять исходную таблицу и переименовывать копию (обратно к исходному имени).

Хотя, у вас должны быть такие вещи, как (FK) ключи, ограничения и т.д. Но используя этот метод, вы избегаете размера журнала badazz, и вы избегаете огромного использования времени для удаления в кусках.

/Snedker