* Заявки Delete
Публикувано на 06 април 2009 от Филип Петров. Записано в DB.
Подобно на INSERT, заявките от тип DELETE са с изключително прост синтаксис:
DELETE FROM <таблица> WHERE <условие>;
Нека демонстрираме един пример с базата данни „banks“. Нека видим първо списък на акаунтите:
mysql> SELECT * FROM accounts; +----+----------+------+-----------+-------------+ | id | amount | type | branch_id | customer_id | +----+----------+------+-----------+-------------+ | 1 | 156.38 | 2 | 1 | 1 | | 2 | 136.22 | 1 | 1 | 2 | | 3 | 42.98 | 1 | 1 | 3 | | 4 | 1236.33 | 1 | 1 | 4 | | 5 | 211.98 | 2 | 1 | 5 | | 6 | 1200.00 | 2 | 2 | 6 | | 7 | 133.48 | 1 | 2 | 7 | | 8 | 256.41 | 2 | 2 | 8 | | 9 | 1331.50 | 2 | 2 | 9 | | 10 | 116.88 | 2 | 2 | 10 | | 11 | 200.91 | 1 | 2 | 10 | | 12 | 99.18 | 1 | 2 | 11 | | 13 | 6712.52 | 1 | 3 | 12 | | 14 | 12000.56 | 1 | 3 | 12 | | 15 | 322.99 | 2 | 3 | 12 | | 16 | 991.63 | 1 | 3 | 13 | | 17 | 559.32 | 2 | 3 | 14 | | 18 | 680.13 | 1 | 3 | 15 | | 19 | 532.57 | 1 | 3 | 15 | | 20 | 402.26 | 1 | 3 | 16 | | 21 | 1536.91 | 2 | 4 | 17 | | 22 | 14921.43 | 1 | 4 | 18 | | 23 | 3910.50 | 1 | 5 | 19 | | 24 | 231.37 | 1 | 5 | 20 | | 25 | 7236.60 | 1 | 5 | 21 | | 26 | 2226.63 | 2 | 5 | 21 | | 27 | 500.00 | 2 | 6 | 22 | +----+----------+------+-----------+-------------+ 27 rows in set (0.00 sec)
Нека изтрием акаунт с id=26:
DELETE FROM accounts WHERE id = 26;
Ако изпълните заявката SELECT отново ще видите, че въпросният ред е изчезнал.
Важно е да се знае, че при използването на FOREIGN KEYS и ON DELETE CASCADE ще бъдат изтрити и записите на редове в таблици, които „сочат“ към записа, който ще бъде изтрит. Например нека видим таблицата „customers“:
mysql> SELECT * FROM customers; +----+-------------------+---------+----------+ | id | name | address | bank_mgr | +----+-------------------+---------+----------+ | 1 | Todor Ivanov | NULL | 1 | | 2 | Petko Stoianov | NULL | 1 | | 3 | Neno Nenov | NULL | 2 | | 4 | Mariana Zaharieva | NULL | 3 | | 5 | Elica Zaharieva | NULL | 3 | | 6 | Atanas Petrov | NULL | 4 | | 7 | Ivan Ivanov | NULL | 4 | | 8 | Zlatomir Petrov | NULL | 4 | | 9 | Mihail Ivchev | NULL | 5 | | 10 | Todor Shtilianov | NULL | 6 | | 11 | Ivailo Ivanov | NULL | 7 | | 12 | George Lucas | NULL | 8 | | 13 | George Harison | NULL | 8 | | 14 | Michael Jackson | NULL | 8 | | 15 | Tony Martin | NULL | 8 | | 16 | Tony McCarter | NULL | 10 | | 17 | Alexander Smith | NULL | 11 | | 18 | Maria Smith | NULL | 11 | | 19 | Alain Delrick | NULL | 12 | | 20 | Devry Henry | NULL | 12 | | 21 | Lenard Renne | NULL | 12 | | 22 | Fontaine Rupert | NULL | 13 | +----+-------------------+---------+----------+
Нека изтрием клиент с id 10:
DELETE FROM customers WHERE id = 10;
Ще видите, че в редовете в таблица „accounts“, чието поле „customer_id“ е било равно на 10, също са изтрити:
mysql> SELECT * FROM accounts
-> ;
+----+----------+------+-----------+-------------+
| id | amount | type | branch_id | customer_id |
+----+----------+------+-----------+-------------+
| 1 | 156.38 | 2 | 1 | 1 |
| 2 | 136.22 | 1 | 1 | 2 |
| 3 | 42.98 | 1 | 1 | 3 |
| 4 | 1236.33 | 1 | 1 | 4 |
| 5 | 211.98 | 2 | 1 | 5 |
| 6 | 1200.00 | 2 | 2 | 6 |
| 7 | 133.48 | 1 | 2 | 7 |
| 8 | 256.41 | 2 | 2 | 8 |
| 9 | 1331.50 | 2 | 2 | 9 |
| 12 | 99.18 | 1 | 2 | 11 |
| 13 | 6712.52 | 1 | 3 | 12 |
| 14 | 12000.56 | 1 | 3 | 12 |
| 15 | 322.99 | 2 | 3 | 12 |
| 16 | 991.63 | 1 | 3 | 13 |
| 17 | 559.32 | 2 | 3 | 14 |
| 18 | 680.13 | 1 | 3 | 15 |
| 19 | 532.57 | 1 | 3 | 15 |
| 20 | 402.26 | 1 | 3 | 16 |
| 21 | 1536.91 | 2 | 4 | 17 |
| 22 | 14921.43 | 1 | 4 | 18 |
| 23 | 3910.50 | 1 | 5 | 19 |
| 24 | 231.37 | 1 | 5 | 20 |
| 25 | 7236.60 | 1 | 5 | 21 |
| 27 | 500.00 | 2 | 6 | 22 |
+----+----------+------+-----------+-------------+
24 rows in set (0.00 sec)
Виждате, че акаунти с id 10 и 11 са изтрити.
Това може да доведе до някои „неудобства“. Нека например се опитаме да изтрием служител с id = 2:
mysql> DELETE FROM employees
-> WHERE id = 2;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constrai
nt fails (`banks`.`customers`, CONSTRAINT `customers_ibfk_1` FOREIGN KEY (`bank_
mgr`) REFERENCES `employees` (`id`))
Проблемът тук е, че в таблицата „customers“ има FOREIGN KEY „bank_mgr“, който сочи към таблицата „employees“, но НЯМА ON DELETE CASCADE. Това всъщност е съвсем нормално, защото ако уволним даден служител не би следвало да прекратяваме договорите с клиентите на банката, които той обслужва. Как тогава все пак да изтрием служител с id = 2?
Отговорът е, че трябва да направим NULL или да променим към друг bank_mgr всички клиенти, които сочат към bank_mgr=2:
UPDATE customers SET bank_mgr = NULL WHERE bank_mgr = 2;
Вече можем да изтрием служител с id = 2:
mysql> DELETE FROM employees
-> WHERE id = 2;
Query OK, 1 row affected (0.08 sec)
Въпреки, че първоначалното впечатление е, че FOREIGN KEYS ни „пречат“ с тази си особеност, това всъщност ни помага значително, защото така се грижим да правилен интегритет на базата данни. Не би трябвало в нашата база данни да има неверни данни, нали?
Тук отново трябва да се обърне изключително внимание на дизайна на базата данни. Хубаво е в ER диаграмата да си отбелязвате изрично коя връзка има ON DELETE CASCADE и коя не. Винаги преди изпълнение на DELETE трябва да прецените засегнатите връзки и ако има такава без ON DELETE CASCADE, то трябва първо да изпълните заявка от тип UPDATE.
В заключение ще кажем, че е възможно да си спестим този труд, като направим външния ключ с опция „ON DELETE SET NULL“. Това всъщност ще свърши абсолютно същата работа, която демонстрирахме по-горе със заявката UPDATE (то естествено беше с обучителна цел). Препоръчително е да се възползвате от тези удобства.
Задача: Изтрийте банка с code = 2
Упътване: В случая не трябва просто да нулирате записите на външния ключ на customers, а трябва и да изтриете редовете. Предполага се, че когато банка бъде изтрита ще бъдат изтрити и нейните клиенти.
Trackback URI | RSS за коментарите
Пусни коментар
Страници
Категории
- C/C++ (45)
- DB (36)
- Dogs (51)
- Food (8)
- History (9)
- Java (33)
- Lada (45)
- Math (104)
- Metodos (35)
- NetSec (36)
- Other (79)
- Politics (32)
- Probability (13)
- VC++.Net (1)
- XHTML/JS (25)
Нови
- Малко снимки от лятото…
- ASCII Лада Нива
- Анимация и обучение чрез забавление
- Активизиране на студентите по време на лекции
- Проблемно-ситуационно обучение