Введение
Помимо чтения данных (статья 394), приложениям нужно их изменять — в статье разберём три основные команды модификации: INSERT (добавление новых строк), UPDATE (изменение существующих), и DELETE (удаление), вместе с их типичными вариациями и осторожностями, без понимания которых легко случайно изменить или удалить значительно больше данных, чем планировалось.
Концепция
INSERT добавляет одну или несколько новых строк в таблицу, явно или неявно (через позиционное соответствие) указывая значения для столбцов. UPDATE изменяет значения указанных столбцов в существующих строках, отбираемых тем же синтаксисом WHERE, что и в SELECT — без WHERE UPDATE изменит абсолютно все строки таблицы, что почти всегда нежелательно и одна из самых частых, разрушительных ошибок начинающих. DELETE удаляет строки целиком, также отбираемые через WHERE с тем же риском при его отсутствии.
Пример кода: INSERT, UPDATE, DELETE
-- INSERT нескольких строк за одну команду — эффективнее множества отдельных INSERT
INSERT INTO customers (id, name, email) VALUES
(2, 'Мария Сидорова', 'maria@example.com'),
(3, 'Алексей Кузнецов', 'alexey@example.com');
-- UPDATE с обязательным WHERE — изменение конкретных, отобранных строк
UPDATE customers
SET email = 'ivan.new@example.com'
WHERE id = 1;
-- UPDATE с вычисляемым значением на основе текущего
UPDATE orders
SET total_amount = total_amount * 1.1 -- увеличение на 10%
WHERE order_date < '2026-01-01';
-- DELETE с WHERE — удаление конкретных строк
DELETE FROM orders
WHERE order_date < '2024-01-01'; -- удаление старых заказов
-- ОПАСНО: DELETE без WHERE удаляет ВСЕ строки таблицы
-- DELETE FROM orders; -- не делайте так без явного, осознанного намерения
-- Безопасная практика: сначала SELECT с тем же условием, чтобы увидеть, что будет затронуто
SELECT * FROM orders WHERE order_date < '2024-01-01'; -- проверка ПЕРЕД реальным DELETE
-- только после проверки результата — выполнение реального DELETE с тем же условием
Пояснения к коду
Множественный INSERT (вставка нескольких строк в одной команде через перечисление через запятую) — не просто синтаксическое удобство, а часто заметно более эффективный способ вставки множества строк по сравнению с отдельной командой INSERT для каждой строки, поскольку СУБД может обработать всю партию данных за одно обращение, минуя повторяющиеся накладные расходы каждой отдельной транзакции. Паттерн «сначала SELECT с тем же условием, потом DELETE/UPDATE» — практическая мера безопасности, особенно ценная при работе непосредственно в командной строке СУБД с реальными, production-данными, позволяющая визуально убедиться, что условие WHERE действительно отбирает именно те строки, которые предполагалось затронуть, прежде чем выполнять необратимое изменение.
Подводные камни
- Выполнение
UPDATE/DELETEбезWHEREпо ошибке (забытое условие, или вставка лишнего символа, превратившего условие в синтаксически валидное, но не то, что предполагалось) — это, возможно, самая частая и потенциально катастрофическая ошибка работы с SQL напрямую, способная мгновенно изменить или удалить все данные таблицы без возможности простого отмена в production-окружении без транзакции (статья 408) или backup (статья 431); привычка явно проверять условие через предварительныйSELECT(как в последнем примере) — практичная защита от такой ошибки. - Отсутствие оборачивания серии связанных модификаций в единую транзакцию (статья 408) — если несколько
INSERT/UPDATE/DELETEкоманд логически должны выполниться все вместе или не выполниться вовсе (например, перевод денег между счетами — одновременное уменьшение одного баланса и увеличение другого), выполнение их как независимых, отдельных команд рискует оставить данные в несогласованном, «наполовину выполненном» состоянии при сбое между отдельными командами. - Игнорирование того, что
UPDATE/DELETEмогут затронуть значительно больше строк, чем ожидалось, из-за неверно сформулированного условияWHERE(например, использованиеORтам, где логически нуженAND, что расширяет, а не сужает условие отбора) — перед выполнением модификации с нетривиальным условием стоит явно проверить логику условия отдельно черезSELECT COUNT(*)с тем жеWHERE, сравнив полученное число с ожидаемым количеством затрагиваемых строк. - Вставка данных без учёта ограничений ссылочной целостности (внешних ключей, статья 397) — попытка вставить заказ со значением
customer_id, не соответствующим никакому реально существующему клиенту, будет отклонена СУБД при правильно настроенном ограничении внешнего ключа, и понимание этого ограничения как защитного механизма (а не просто «ошибки», которую нужно подавить) важно для правильного проектирования порядка операций вставки связанных данных (сначала родительские записи, затем дочерние, ссылающиеся на них).