Тази статия съдържа основния SQL DELETE
изрази, които начинаещите могат да използват, за да изтрият данни от таблиците на своите бази данни.
Изтриване на един ред
Ето основен пример за SQL DELETE
изявление.
DELETE FROM Owners
WHERE OwnerId = 5;
В този случай изтриваме реда, където е OwnerId
колоната има стойност 4
.
DELETE
операторът започва с DELETE FROM
, последвано от името на таблицата (т.е. таблицата, която съдържа данните, които искате да изтриете).
В някои системи за управление на бази данни (СУБД) FROM
ключовата дума не е задължителна, но е добра идея да я включите за по-добра преносимост (в случай, че трябва да стартирате същия код на различна СУБД).
Винаги трябва да включвате WHERE
клауза, освен ако не искате да изтриете всички редове от таблицата.
Да, правилно прочетохте. Пропускане на WHERE
клауза ще изтрие всички редове в таблицата.
Повечето СУБД имат различни други опции, които можете да използвате с DELETE
изявление, но изброените тук са най-често използваните.
Имайте предвид, че DELETE
оператор изтрива целия ред. Не можете да изтриете стойността на отделна колона в ред. За да направите това, използвайте SQL UPDATE
изявление.
Пример
В този пример изтриваме данни от таблица.
Първо, нека видим какво има в таблицата.
SELECT * FROM Owners;
Резултат:
+-----------+-------------+------------+----------------+-------------------+ | OwnerId | FirstName | LastName | Phone | Email | |-----------+-------------+------------+----------------+-------------------| | 1 | Homer | Connery | (308) 555-0100 | [email protected] | | 2 | Bart | Pitt | (231) 465-3497 | [email protected] | | 3 | Nancy | Stallone | (489) 591-0408 | NULL | | 4 | Boris | Biden | (349) 611-8908 | [email protected] | | 5 | Woody | Eastwood | (308) 555-0112 | [email protected] | +-----------+-------------+------------+----------------+-------------------+
Добре, нека изтрием номер на собственик 5, след което отново изберете таблицата.
DELETE FROM Owners
WHERE OwnerId = 5;
SELECT * FROM Owners;
Резултат:
+-----------+-------------+------------+----------------+-------------------+ | OwnerId | FirstName | LastName | Phone | Email | |-----------+-------------+------------+----------------+-------------------| | 1 | Homer | Connery | (308) 555-0100 | [email protected] | | 2 | Bart | Pitt | (231) 465-3497 | [email protected] | | 3 | Nancy | Stallone | (489) 591-0408 | NULL | | 4 | Boris | Biden | (349) 611-8908 | [email protected] | +-----------+-------------+------------+----------------+-------------------+
Можем да видим, че последният ред е изтрит, както е посочено.
Външни ключове
Може да получите грешка, ако се опитате да изтриете данни, които са посочени от външен ключ в друга таблица. Това е така, защото таблицата, от която се опитвате да изтриете данни, е родителската таблица във връзка. Таблицата с външния ключ (дъщерната таблица) разчита на данни в родителската таблица (т.е. данни, които се опитвате да изтриете).
Дали ще получите грешка или не ще зависи от това как е конфигуриран външният ключ. Повечето СУБД поддържат различни опции за справяне с тази ситуация. Такива опции могат да включват, повдигане на грешка, каскадно изтриване към таблицата с външни ключове (т.е. изтриване на реда от дъщерната таблица), задаване на външния ключ на NULL
, или задаване на стойността му по подразбиране.
Ето пример за опит за изтриване на ред, който е препратен от външен ключ.
DELETE FROM Owners
WHERE OwnerId = 3;
Резултат:
Msg 547, Level 16, State 0, Line 1 The DELETE statement conflicted with the REFERENCE constraint "FK_Pets_Owners". The conflict occurred in database "PetHotel", table "dbo.Pets", column 'OwnerId'. The statement has been terminated.
В този случай е възникнала грешка и редът не е изтрит.
В този пример Owners.OwnerId
колоната е първичният ключ на тази таблица. Друга таблица, наречена Pets
има OwnerId
колона, която препраща към тази колона с първичен ключ и в този случай има поне един ред, който препраща номер на собственик 3.
Ако наистина исках да изтрия този ред, ще трябва да актуализирам данните в дъщерната таблица, така че да няма редове да сочат към този собственик. Или това, или модифицирайте външния ключ, така че да използва различна опция, когато се извършват операции за изтриване на първичния ключ. Промяната на външен ключ може да бъде нежелана опция, в зависимост от това, което трябва да направите. В зависимост от вашата СУБД може също да се наложи да премахнете съществуващия ключ и да го създадете отново.
Във всеки случай тази грешка е нещо добро, защото ни предупреждава за проблем, който ще имаме, ако изтрием този ред. Помага за налагането на референтната цялост.
Внимание! Забравяме WHERE
Клауза
DELETE
изявлението може да бъде много опасно изявление. Ако пропуснете WHERE
клауза, ще изтриете всички редове в таблицата.
За щастие, може да бъдете спасени от ограничения на външния ключ, ако се опитате да изтриете данни от родителската таблица на връзка.
Но какво ще стане, ако не е така. Ами ако няма грешки от вашите оператори за изтриване?
Нека разберем!
Нека изпълним още един DELETE
изявление, но този път ще забравим да включим WHERE
клауза. Освен това този път ще го изпълним срещу таблица, която не е родител във връзка.
Първо, нека видим какво има в таблицата.
SELECT * FROM Pets;
Резултат:
+---------+-------------+-----------+-----------+------------+ | PetId | PetTypeId | OwnerId | PetName | DOB | |---------+-------------+-----------+-----------+------------| | 1 | 2 | 3 | Fluffy | 2020-11-20 | | 2 | 3 | 3 | Fetch | 2019-08-16 | | 3 | 2 | 2 | Scratch | 2018-10-01 | | 4 | 3 | 3 | Wag | 2020-03-15 | | 5 | 1 | 1 | Tweet | 2020-11-28 | | 6 | 3 | 4 | Fluffy | 2020-09-17 | | 7 | 3 | 2 | Bark | NULL | | 8 | 2 | 4 | Meow | NULL | +---------+-------------+-----------+-----------+------------+
Добре, така че имаме осем домашни любимци. Всъщност можем да видим, че три домашни любимци са собственост на собственик номер 3 – собственикът, когото се опитахме да изтрием в предишния пример. Ето защо получихме грешката.
Както и да е, нека продължим и стартираме нашия DELETE
изявление без WHERE
клауза, след което проверете отново таблицата
DELETE FROM Pets;
SELECT * FROM Pets;
Резултат:
(8 rows affected) (0 rows affected)
(8 rows affected)
част означава, че осем реда са изтрити.
(0 rows affected)
част означава, че не са избрани редове (защото в таблицата няма редове.
Опа!
Може да има моменти, в които всъщност трябва да изтриете всички редове в таблицата. В зависимост от размера на таблицата, това изявление ще е всичко, от което се нуждаете.
Ако трябва да изтриете по-голяма таблица, има и TRUNCATE TABLE
, който премахва всички редове от таблица или определени дялове на таблица, без да регистрира отделните изтривания на редове (DELETE
изявление регистрира тези изтривания).
Следователно, TRUNCATE TABLE
е по-бърз и използва по-малко ресурси на системата и регистрационните файлове на транзакциите.
Пример за използване на TRUNCATE TABLE
:
TRUNCATE TABLE Owners;
Имайте предвид, че това може да не работи, ако таблицата се препраща от ограничение за външен ключ, дори ако няма дъщерни редове. В такива случаи DELETE
може да работи вместо това.