Урок 7. Изменение и удаление — UPDATE и DELETE
Данные редко остаются неизменными: цены растут, товар продаётся, покупатель уходит. Для этого есть две команды: UPDATE меняет значения в строках, DELETE удаляет строки. Обе опасны одинаково — одна забытая строчка в запросе меняет всю таблицу.
Тренируйтесь с возможностью отмены
Запросы урока меняют учебную таблицу products, а следующим урокам она нужна в исходном виде. Поэтому в sqlite3 начните урок командой:
BEGIN;Она открывает транзакцию: все изменения до команды ROLLBACK можно отменить разом. Подробно о транзакциях — в последнем уроке, пока достаточно знать, что ROLLBACK в конце урока вернёт всё как было.
В DB Browser for SQLite BEGIN не нужен: не нажимайте «Write Changes», а в конце урока нажмите «Revert Changes».
UPDATE — изменить строки
Ручка подорожала до 3 рублей:
UPDATE products SET price = 3 WHERE id = 1;
SELECT id, name, price FROM products WHERE id = 1;| id | name | price |
|---|---|---|
| 1 | Ручка | 3 |
После UPDATE — таблица, после SET — что присвоить, после WHERE — каким строкам. Несколько столбцов меняют через запятую:
UPDATE products SET price = 65, qty = 10 WHERE name = 'Наушники';Новое значение можно вычислить из старого. Продали два рюкзака:
UPDATE products SET qty = qty - 2 WHERE id = 3;
SELECT name, qty FROM products WHERE id = 3;| name | qty |
|---|---|
| Рюкзак | 10 |
qty = qty - 2 читается «новый остаток = старый остаток минус 2». Так же поднимают цены целой категории:
UPDATE products SET price = price + 1 WHERE category = 'Канцелярия';
SELECT name, price FROM products WHERE category = 'Канцелярия';| name | price |
|---|---|
| Ручка | 4 |
| Тетрадь | 4 |
| Пенал | 13 |
Сколько строк изменила последняя команда, в SQLite показывает SELECT changes(); — здесь 3. MySQL и PostgreSQL сообщают это сами после каждой команды.
Ограничения таблицы действуют и при изменении: UPDATE products SET price = -5 WHERE id = 2; не выполнится, ошибка — CHECK constraint failed.
DELETE — удалить строки
Удалите товары, которых нет на складе. Сначала посмотрите, какие это строки:
SELECT id, name, qty FROM products WHERE qty = 0;| id | name | qty |
|---|---|---|
| 5 | Глобус | 0 |
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; сотрёт все заказы. Подтверждения не будет, отменить без транзакции или резервной копии нельзя.
Проверьте на себе (транзакция открыта, всё вернётся):
UPDATE products SET price = 1;
SELECT name, price FROM products;| name | price |
|---|---|
| Ручка | 1 |
| Тетрадь | 1 |
| Рюкзак | 1 |
| Пенал | 1 |
| Калькулятор | 1 |
| Наушники | 1 |
| Сумка для ноутбука | 1 |
Привычки, которые спасают данные:
- Сначала напишите
SELECTс тем жеWHEREи посмотрите, какие строки попадут под изменение. - Убедитесь, что их столько, сколько ожидали, и только потом замените
SELECT …наUPDATE … SET …илиDELETE. - Меняйте строки по ключу (
WHERE id = 5), а не по имени или другому неуникальному столбцу, если нужна одна строка. - На рабочей базе — сначала резервная копия или хотя бы транзакция:
BEGIN;, изменение, проверка, затем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 | удаляет таблицу вместе со строками |
Подробнее о разнице — справка Как удалить таблицу или все строки.
Отмените изменения урока
ROLLBACK;
SELECT COUNT(*) FROM products;| COUNT(*) |
|---|
| 8 |
Все восемь товаров на месте, цены прежние. В DB Browser for SQLite — кнопка «Revert Changes». Если вы выполнили запросы без BEGIN, пересоздайте таблицу по третьему уроку.
Коротко
UPDATE таблица SET столбец = значение WHERE условие— изменить строки; значение можно вычислить из старого.DELETE FROM таблица WHERE условие— удалить строки.- Без
WHEREобе команды затрагивают всю таблицу — сначала проверяйте условие черезSELECT. changes()в SQLite показывает, сколько строк изменено.BEGIN…ROLLBACKпозволяет отменить всё, что сделано послеBEGIN.