Глиф Учебники

Урок 7. Изменение и удаление — UPDATE и DELETE

Курс «SQL» · урок 7 из 10 · 4 минуты чтения

Данные редко остаются неизменными: цены растут, товар продаётся, покупатель уходит. Для этого есть две команды: UPDATE меняет значения в строках, DELETE удаляет строки. Обе опасны одинаково — одна забытая строчка в запросе меняет всю таблицу.

Тренируйтесь с возможностью отмены

Запросы урока меняют учебную таблицу products, а следующим урокам она нужна в исходном виде. Поэтому в sqlite3 начните урок командой:

SQL
BEGIN;

Она открывает транзакцию: все изменения до команды ROLLBACK можно отменить разом. Подробно о транзакциях — в последнем уроке, пока достаточно знать, что ROLLBACK в конце урока вернёт всё как было.

В DB Browser for SQLite BEGIN не нужен: не нажимайте «Write Changes», а в конце урока нажмите «Revert Changes».

UPDATE — изменить строки

Ручка подорожала до 3 рублей:

SQL
UPDATE products SET price = 3 WHERE id = 1;
SELECT id, name, price FROM products WHERE id = 1;
idnameprice
1Ручка3

После UPDATE — таблица, после SET — что присвоить, после WHERE — каким строкам. Несколько столбцов меняют через запятую:

SQL
UPDATE products SET price = 65, qty = 10 WHERE name = 'Наушники';

Новое значение можно вычислить из старого. Продали два рюкзака:

SQL
UPDATE products SET qty = qty - 2 WHERE id = 3;
SELECT name, qty FROM products WHERE id = 3;
nameqty
Рюкзак10
UPDATE products какая таблица SET qty = qty - 2 что присвоить WHERE id = 3 каким строкам до id name qty 2 Тетрадь 300 3 Рюкзак 12 4 Пенал 40 после id name qty 2 Тетрадь 300 3 Рюкзак 10 4 Пенал 40 12 - 2 не тронута изменена не тронута
В UPDATE после SET сказано, что присвоить, а после WHERE — каким строкам: условие id = 3 выбирает только рюкзак, его остаток 12 становится 10, остальные строки не меняются.

qty = qty - 2 читается «новый остаток = старый остаток минус 2». Так же поднимают цены целой категории:

SQL
UPDATE products SET price = price + 1 WHERE category = 'Канцелярия';
SELECT name, price FROM products WHERE category = 'Канцелярия';
nameprice
Ручка4
Тетрадь4
Пенал13

Сколько строк изменила последняя команда, в SQLite показывает SELECT changes(); — здесь 3. MySQL и PostgreSQL сообщают это сами после каждой команды.

Ограничения таблицы действуют и при изменении: UPDATE products SET price = -5 WHERE id = 2; не выполнится, ошибка — CHECK constraint failed.

DELETE — удалить строки

Удалите товары, которых нет на складе. Сначала посмотрите, какие это строки:

SQL
SELECT id, name, qty FROM products WHERE qty = 0;
idnameqty
5Глобус0
SQL
DELETE FROM products WHERE qty = 0;
SELECT COUNT(*) FROM products;
COUNT(*)
7

DELETE FROM таблица WHERE условие удаляет все строки, подходящие под условие. Удаляется строка целиком — удалить «только цену» нельзя: для этого UPDATE … SET price = NULL (если столбец допускает NULL).

После удаления в нумерации остаётся дыра: следующий товар получит не номер 5, а номер после наибольшего — 9. Это нормально: id нужен, чтобы отличать строки, а не чтобы считать их.

Самое опасное — забыть WHERE

UPDATE и DELETE без WHERE применяются ко всем строкам таблицы. UPDATE products SET price = 1; сделает все товары рублёвыми, DELETE FROM orders; сотрёт все заказы. Подтверждения не будет, отменить без транзакции или резервной копии нельзя.

Проверьте на себе (транзакция открыта, всё вернётся):

SQL
UPDATE products SET price = 1;
SELECT name, price FROM products;
nameprice
Ручка1
Тетрадь1
Рюкзак1
Пенал1
Калькулятор1
Наушники1
Сумка для ноутбука1
С условием WHERE UPDATE products SET price = 3 WHERE id = 1; Ручка 2 → 3 Тетрадь 3 Рюкзак 85 Пенал 12 Глобус 45 Калькулятор 30 Наушники 60 Сумка для ноутбука 70 изменена 1 строка Без WHERE UPDATE products SET price = 1; Ручка 1 Тетрадь 1 Рюкзак 1 Пенал 1 Калькулятор 1 Наушники 1 Сумка для ноутбука 1 изменены все 7 строк
UPDATE с условием WHERE id = 1 меняет одну строку, а UPDATE products SET price = 1 без WHERE переписывает цену во всех строках таблицы.

Привычки, которые спасают данные:

  1. Сначала напишите SELECT с тем же WHERE и посмотрите, какие строки попадут под изменение.
  2. Убедитесь, что их столько, сколько ожидали, и только потом замените SELECT … на UPDATE … SET … или DELETE.
  3. Меняйте строки по ключу (WHERE id = 5), а не по имени или другому неуникальному столбцу, если нужна одна строка.
  4. На рабочей базе — сначала резервная копия или хотя бы транзакция: BEGIN;, изменение, проверка, затем COMMIT; (сохранить) или ROLLBACK; (отменить).
1 BEGIN; изменения можно будет отменить 2 SELECT id, name, qty FROM products WHERE qty = 0; попадёт 1 строка: 5 · Глобус · 0 3 DELETE FROM products WHERE qty = 0; тот же WHERE — удалится Глобус 4 SELECT COUNT(*) FROM products; проверка: осталось 7 столько строк, сколько ждали? — да всё верно что-то не так COMMIT; сохранить ROLLBACK; отменить
Безопасное удаление по шагам: открыть транзакцию, через SELECT с тем же WHERE посмотреть, какие строки попадут под удаление, удалить, проверить результат и только потом выбрать COMMIT или ROLLBACK.

MySQL Workbench по умолчанию работает в безопасном режиме: UPDATE и DELETE без условия по ключу он не выполняет и показывает ошибку 1175 (You are using safe update mode). Это защита, а не сбой: добавьте в запрос WHERE по первичному ключу.

Удалить всё и удалить таблицу

КомандаЧто делает
DELETE FROM orders WHERE …удаляет подходящие строки
DELETE FROM ordersудаляет все строки, таблица остаётся
TRUNCATE TABLE ordersбыстро очищает таблицу (MySQL, PostgreSQL; в SQLite этой команды нет)
DROP TABLE ordersудаляет таблицу вместе со строками

Подробнее о разнице — справка Как удалить таблицу или все строки.

Отмените изменения урока

SQL
ROLLBACK;
SELECT COUNT(*) FROM products;
COUNT(*)
8

Все восемь товаров на месте, цены прежние. В DB Browser for SQLite — кнопка «Revert Changes». Если вы выполнили запросы без BEGIN, пересоздайте таблицу по третьему уроку.

Коротко

Проверьте себя

1. Что сделает UPDATE products SET qty = 0;?
2. Как увеличить остаток рюкзака (id = 3) на 5 штук?
3. Как безопаснее всего выполнить DELETE на рабочей базе?
4. Чем DELETE FROM orders; отличается от DROP TABLE orders;?