DELETE: изтриване на редове
Накратко: DELETE FROM изтрива редовете, които WHERE избере, а без WHERE изпразва цялата таблица.
Проблем
Махни отзива ми
През януари Мария писа отзив за праха за пране: „Пакетът пристигна скъсан.“ Магазинът ѝ прати нов пакет. Сега Мария пише в поддръжката и моли отзивът да се махне.
Редът трябва да изчезне от reviews. Само той, без другите отзиви на Мария.
Идеята
DELETE FROM … WHERE
DELETE FROM казва от коя таблица, а WHERE казва кои редове:
Отзив 7 го няма, а другият отзив на Мария, за белия хляб, си стои. DELETE маха цели редове. Колони не се изброяват.
Редът е изтрит само в тази база. „Нова база“ го връща.
Пробвай
Закрит профил
Теодора Генова (клиент 19) се регистрира през септември, но не е поръчала нищо. Днес закрива профила си. Изтрий я.
Решение
DELETE FROM customers WHERE id = 19;DELETE FROM customers WHERE id = 19. Остават 19 клиенти. Теодора няма поръчки и отзиви, затова базата позволява. При следващата карта не е така.
Виж го
Клиент с поръчки
Мария също иска да закрие профила си. Опитай:
Базата отказва. Мария има 12 поръчки и два отзива, а те сочат към нея с външен ключ (customer_id). Ако редът ѝ изчезне, поръчките ще са на никого.
Това е правило на таблицата, както UNIQUE и CHECK от първия урок. В следващия модул ще го пишеш сам и ще избираш какво да става с поръчките, когато клиентът се изтрие.
Виж го
DELETE без WHERE
Забравиш ли WHERE, изчезват всички редове:
16 отзива, събирани цяла година, изчезват с една заявка. Таблицата остава, но е празна. Натисни „Нова база“, за да ги върнеш.
С клиентите не става така:
Повечето клиенти имат поръчки, затова цялата заявка се отказва. Не се трият и клиентите без поръчки: или се изпълнява цялата заявка, или нищо. Затова и тук важи навикът от предишния урок: първо SELECT със същото WHERE.
Идеята
Меко изтриване
Георги Петров се отказва от новата си поръчка 57. Изтриването не става, защото в поръчката има продукти:
Можеш първо да изтриеш редовете ѝ от order_items, а после самата поръчка. Но магазините рядко го правят. Вместо това поръчката се отказва:
Това е меко изтриване: редът остава, но е отбелязан като изтрит или отказан. Защо магазините го предпочитат:
- Отчетите остават верни. Колко поръчки се отказват и защо е важен въпрос.
- Счетоводството има нужда от всяка поръчка, по която е имало плащане.
- Поддръжката вижда историята, когато клиентът се обади.
- Грешката се поправя. Отказаното се връща с един
UPDATE. Изтритото не се връща.
Цената е, че всяка заявка трябва да помни за отказаните. Отчетът за продажбите трябва да има WHERE status <> 'cancelled'.
По-точно, за любопитните
В много системи всяка таблица има колона deleted_at: NULL за живите редове, дата за „изтритите“. Тогава всяка заявка има WHERE deleted_at IS NULL. Как се добавя колона към таблица ще видиш в следващия модул.
Понякога изтриването е задължително. Когато човек поиска данните му да се махнат (правото „да бъдеш забравен“ в GDPR), личните данни трябва да изчезнат. Често името и имейлът се изтриват или заменят, а поръчките остават без тях за счетоводството.
Пробвай
Без краставици
Краставиците (продукт 13) свършиха. Магазинът ги маха от новата поръчка 57, а другите продукти в нея остават.
Решение
DELETE FROM order_items WHERE order_id = 57 AND product_id = 13;DELETE FROM order_items WHERE order_id = 57 AND product_id = 13. Двете условия заедно: без първото краставиците щяха да изчезнат и от старите поръчки. Проверява се цялата таблица order_items.
Упражнение
Две задачи
1. Борис Митев (boris.mitev@example.com) иска отзивите му да се махнат. Изтрий ги, като намериш клиента по имейла с подзаявка.
Без отзивите на Борис:
Решение
DELETE FROM reviews
WHERE customer_id = (SELECT id FROM customers WHERE email = 'boris.mitev@example.com');DELETE FROM reviews WHERE customer_id = (SELECT id FROM customers WHERE email = 'boris.mitev@example.com'). Той има един отзив, за кафето. Остават 15. Самия Борис не можеш да изтриеш: той има поръчки.
2. Баницата и краставиците свършиха и няма да има до края на месеца. Махни изчерпаните продукти (наличност 0) от новите поръчки (status = 'new'). Старите поръчки са история и не се пипат.
Без изчерпаните продукти в новите поръчки:
Решение
DELETE FROM order_items
WHERE product_id IN (SELECT id FROM products WHERE stock = 0)
AND order_id IN (SELECT id FROM orders WHERE status = 'new');DELETE FROM order_items WHERE product_id IN (SELECT id FROM products WHERE stock = 0) AND order_id IN (SELECT id FROM orders WHERE status = 'new'). Изчезват три реда, от поръчки 27, 46 и 57. Без второто условие щяха да изчезнат 18 реда, и от доставени поръчки. Полето започва със SELECT, който ги показва.
Тест
Провери се
Свързани уроци
Раздел „Свързани уроци“- Нужно отпреди: Първичен и външен ключ · Подзаявки · INSERT: нови редове · UPDATE: промяна на редове
- Продължава в: UPSERT: вмъкни или обнови · Базата данни: от създаването до DROP · Външни ключове: връзки между таблиците · Нормализация
- Задачи по темата: Промяна на данните