Как очистить таблицу в Firebird

Короткий ответ

В Firebird нет команды TRUNCATE TABLE — ни в 2.5, ни в 3.0, ни в 4.0, ни в 5.0. Это первое, что нужно принять, если вы пришли из PostgreSQL, MySQL или MSSQL. Вместо неё — три подхода в зависимости от размера таблицы и цели:

Ниже каждый способ с нюансами.

Простой случай: DELETE FROM

DELETE FROM orders_log;
COMMIT;

Для таблицы на тысячи-другую записей этого достаточно. Но помните про побочные эффекты:

Сброс генераторов

После очистки часто нужно, чтобы счётчик первичного ключа начался заново:

ALTER SEQUENCE orders_log_id_seq RESTART WITH 0;

В Firebird 2.5 и старше работает устаревший, но живой синтаксис SET GENERATOR orders_log_id_seq TO 0;. Не забудьте: если генератор общий на несколько таблиц (редко, но бывает), сброс сломает уникальность в соседней.

Большая таблица: удаляем частями

Миллионы строк одним DELETE — это длинная транзакция, растущий журнал и страдающий сервер. Правильный путь — удалять порциями с коммитами между ними. Через EXECUTE BLOCK:

EXECUTE BLOCK
AS
BEGIN
  WHILE (1=1) DO
  BEGIN
    DELETE FROM orders_log
    WHERE RDB$DB_KEY IN (
      SELECT RDB$DB_KEY FROM orders_log ROWS 10000
    );
    IF (ROW_COUNT = 0) THEN LEAVE;
    COMMIT;
  END
END

Смысл один: не держать в одной транзакции миллионы изменений. Альтернативы — удалять диапазонами по первичному ключу (WHERE id BETWEEN :a AND :b) с коммитами между частями, или DELETE ... FETCH FIRST n ROWS ONLY в новых версиях.

После полного удаления стоит дать базе собрать мусор — при следующем sweep или явно.

Радикальный вариант: пересоздание

Для очень больших таблиц часто быстрее выгрузить метаданные и пересоздать таблицу:

isql -x база > create_table.sql   # выгрузить DDL
DROP TABLE orders_log;
-- выполнить сохранённый DDL

Быстро и чисто, но: данные теряются безвозвратно (очевидно, но напомним), права на таблицу надо выдать заново, зависимые объекты (вьюхи, внешние ключи из других таблиц) пересоздать. Подходит для журналов и логов, содержимое которых не жалко.

Типичные грабли

СимптомПричинаЧто делать
DELETE идёт вечностьМиллионы строк в одной транзакцииПакетное удаление с коммитами
Файл базы вырос после удаленияЖурнал изменений + не собран мусорКоммиты порциями, дать sweep
После очистки PK продолжается с 100500Генераторы не сбрасываются самиALTER SEQUENCE ... RESTART WITH 0
Ошибка violation of FOREIGN KEYЗависимые таблицы без CASCADEСначала очистить дочерние или добавить CASCADE

Что почитать дальше

Обсуждение