Удаление в SQL: как не стереть лишние строки
Команда DELETE может убрать одну запись, тысячи строк или всю таблицу, если пропустить условие. На примере PostgreSQL 16 разберём безопасный порядок действий: сначала проверить выборку, затем удалить и убедиться в результате.

В SQL одна пропущенная часть запроса — WHERE — может превратить удаление отменённого заказа в удаление всех заказов. Ниже — короткая практика для PostgreSQL 16: на временной таблице вы создадите данные, проверите условие, удалите выбранную строку и научитесь отменять операцию до фиксации.
Что подготовить
Понадобится подключение к PostgreSQL 16 и клиент, в котором можно выполнять SQL-запросы: например, psql или графический интерфейс с редактором SQL. Все примеры работают с временной таблицей: она доступна только в текущем подключении и не меняет постоянные таблицы базы. Команды выполняйте по порядку в одной сессии.
Термин. Транзакция — группа операций, которую можно подтвердить целиком или отменить. Пока изменения не зафиксированы, команда ROLLBACK может вернуть базу к состоянию до начала транзакции.
Удаляйте в три проверки
1. Создайте тестовые данные
Начните с временной таблицы. Заодно проверьте, что подключились к нужной базе: запрос ниже создаёт отдельный тестовый набор и не затрагивает ваши рабочие таблицы.
CREATE TEMP TABLE orders (
id integer PRIMARY KEY,
status text NOT NULL,
created_at date NOT NULL
);
INSERT INTO orders (id, status, created_at) VALUES
(1, 'cancelled', DATE '2023-12-20'),
(2, 'paid', DATE '2023-12-21'),
(3, 'cancelled', DATE '2024-02-10');
SELECT * FROM orders ORDER BY id;
Проверка: запрос SELECT должен показать три строки. Если таблица уже существует в этой сессии и команда CREATE TEMP TABLE сообщает об ошибке, закройте соединение и подключитесь заново либо используйте другое имя тестовой таблицы.
2. Сначала выполните SELECT с тем же условием
Допустим, нужно убрать только отменённые заказы, созданные до 2024 года. До удаления проверьте условие отдельным SELECT:
SELECT id, status, created_at
FROM orders
WHERE status = 'cancelled'
AND created_at < DATE '2024-01-01';
Проверка: должна вернуться ровно одна строка — заказ с id 1. Если результат не совпадает с тем, что вы хотите удалить, не переходите к DELETE. Уточните условие и повторите SELECT.
3. Удалите найденные строки и посмотрите результат
В PostgreSQL 16 DELETE принимает условие WHERE, а RETURNING позволяет получить удалённые значения прямо в ответе:
DELETE FROM orders
WHERE status = 'cancelled'
AND created_at < DATE '2024-01-01'
RETURNING id, status, created_at;
Проверка: RETURNING должен показать удалённый заказ с id 1. Затем выполните SELECT * FROM orders ORDER BY id; в таблице должны остаться строки с id 2 и 3. Если клиент показывает число затронутых строк, сверьте и его: ожидается одна.
Как не потерять возможность отмены
Проверьте запрос в транзакции
Если сомневаетесь в условии, сначала выполните удаление внутри транзакции и отмените его. Эти команды нужно запускать в одном подключении; не включайте режим автоматической фиксации для отдельных запросов.
BEGIN;
DELETE FROM orders
WHERE status = 'cancelled'
RETURNING id, status, created_at;
SELECT * FROM orders ORDER BY id;
ROLLBACK;
Проверка: внутри транзакции вы увидите строки, выбранные для удаления, а после ROLLBACK повторный SELECT должен показать исходные три записи. Когда убедились, что условие правильное, выполните DELETE отдельно и зафиксируйте транзакцию командой COMMIT, если начали её вручную.
В некоторых графических клиентах транзакции могут фиксироваться автоматически или управляться настройками интерфейса. Если после ROLLBACK данные не вернулись, проверьте режим транзакций и журнал выполненных команд: возможно, DELETE уже был зафиксирован.
Перед опасным DELETE проверьте не саму команду, а выборку: SELECT с тем же WHERE должен вернуть именно те строки, которые вы готовы потерять.
Что важно не перепутать
- DELETE без WHERE удаляет все строки таблицы. Таблица при этом остаётся, как и её структура. Не запускайте такой запрос ради проверки.
- TRUNCATE и DELETE — не одно и то же. TRUNCATE очищает таблицу целиком и имеет отдельные особенности, в том числе при работе со связанными таблицами. Для выборочного удаления используйте DELETE с условием.
- DROP удаляет объект базы данных. Если выполнить DROP TABLE, исчезнет сама таблица, а не только её записи. Для удаления записей эта команда не подходит.
- NULL проверяют через IS NULL. Условие column = NULL не сработает как обычное сравнение. Для удаления строк с пустым значением используйте WHERE column IS NULL.
- Внешний ключ может остановить удаление. Если на запись ссылаются строки другой таблицы, PostgreSQL может запретить DELETE. Не обходите ошибку удалением связанных данных наугад: выясните, какие записи ссылаются на цель и какое поведение настроено у ограничения.
DELETE удаляет данные из таблицы, но не всегда означает, что соответствующая информация исчезла из резервных копий, журналов или реплик. Если задача связана с требованиями к хранению или уничтожению данных, одной SQL-команды может быть недостаточно.
Если запрос не сработал
- «relation does not exist». PostgreSQL не нашёл таблицу в текущем подключении. Проверьте имя и схему; временная таблица из примера пропадёт после завершения сессии.
- «column does not exist». В запросе указано неверное имя столбца. Сверьте его с определением таблицы, включая написание и регистр, если имя создавали в кавычках.
- «violates foreign key constraint». На удаляемую запись ссылается другая таблица. Изучите связь и согласуйте порядок удаления с правилами приложения, а не удаляйте связанные строки вслепую.
- Удалилось ноль строк. Условие не совпало с данными. Повторите SELECT с тем же WHERE и проверьте значения, даты и обработку NULL.
Что делать дальше
Повторите шаги на временной таблице, а перед запросом к постоянным данным сохраните результат SELECT или используйте транзакцию с проверкой. Для больших таблиц отдельно оцените, сколько строк затронет условие и сколько времени займёт операция: массовое удаление может создавать нагрузку и блокировать работу приложения. Удаление по связям, резервное копирование и мягкое удаление — отдельные темы; здесь главное правило простое: сначала подтвердите выборку, затем удаляйте.
Редактор изображений: Убрать лишнее, заменить фон, добавить объект, расширить кадр — на вашем изображении.
Спросить за 20 ₽Источники: PostgreSQL 16: DELETE, PostgreSQL 16: управление транзакциями
Частые вопросы
Что будет, если выполнить DELETE без WHERE?
Можно ли отменить DELETE?
Почему DELETE не удаляет строку, хотя она есть?
Чем DELETE отличается от TRUNCATE?
Подойдут ли эти примеры для MySQL или SQLite?
Что делать, если PostgreSQL запрещает удаление из-за внешнего ключа?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.