Настоящата статия се фокусира върху леко разширено използване на израза DELETE за премахване на един или повече записи (редове) от таблица. Въпреки че е насочен предимно към начинаещи, неговите съвети могат да бъдат полезни за всички специалисти по бази данни.
Предварителни условия:Основни сценарии на оператора DELETE
Ако все още не сте запознати с основните приложения на израза Delete, бихме ви препоръчали да прегледате предишната статия SQL Server DELETE – Премахване на един или повече редове от таблица. Тази статия се фокусира върху следните аспекти:
- Създаване на примерна база данни.
- Изпълнение на SQL скриптове срещу примерната база данни.
- Създаване на таблица в примерна база данни и вмъкване на данни в нея.
- Изтриване на всички редове от таблица.
- Изтриване на един или повече редове от таблица въз основа на условие.
- Изтриване на един или повече редове от таблица въз основа на множество условия.
Тези данни са от решаващо значение за разбиране, преди да преминем към леко разширената употреба на израза Delete, така че прегледайте тази статия, ако досега нямате необходимата информация.
Леко усъвършенствани сценарии за израза DELETE
Както при всяко друго ръководство, първо трябва да настроим примерна база данни, за да тестваме безопасното изпълнение на нашите скриптове срещу нея.
Съвет за примерната настройка на базата данни
Горещо бих препоръчал първо да инсталирате локално на вашата машина SQL Server Developer Edition. По-добре е за учене и тестване.
Изтегляне на изданието за разработчици на SQL Server
Настройте примерна база данни (WatchesDelSample)
Ще настроим база данни, наречена WatchesDelSample. Тази база данни съдържа следните три таблици:
- Гледайте.
- Цвят.
- Тип на часовник.
Таблицата Watch е основната. Той съдържа името, цвета и вида на часовника. Информацията както за вида, така и за цвета идва от двете референтни таблици Цвят и WatchType свързани чрез външни ключове.
Настройте примерната база данни със следния скрипт:
-- Create sample database WatchesDelSample
USE MASTER
GO
CREATE DATABASE WatchesDelSample
GO
USE WatchesDelSample
-- Creating a reference table WatchType
CREATE TABLE dbo.WatchType
(
WatchTypeId INT IDENTITY(1,1),
Name VARCHAR(50)NOT NULL,
Detail VARCHAR(200)NULL
CONSTRAINT PK_WatchType_WatchTypeId PRIMARY KEY (WatchTypeId)
)
GO
-- Populating (adding rows to the) table WatchType
SET IDENTITY_INSERT dbo.WatchType ON
GO
INSERT INTO dbo.WatchType
(
WatchTypeId
,Name
,Detail
)
VALUES
(
1 -- ID - INT Primary Key
,'Analogue' -- Name - varchar(50) NOT NULL
,'This is Analogue' -- Detail - varchar(200)
),
(
2 -- ID - INT Primary Key
,'Digital' -- Name - varchar(50) NOT NULL
,'This is Digital' -- Detail - varchar(200)
),
(
3 -- ID - INT Primary Key
,'Sports' -- Name - varchar(50) NOT NULL
,'This is Sports' -- Detail - varchar(200)
);
GO
SET IDENTITY_INSERT dbo.WatchType OFF
GO
-- Creating a reference table Color
CREATE TABLE dbo.Color
(
ColorId INT IDENTITY(1,1),
Name VARCHAR(50)NOT NULL,
Detail VARCHAR(200)NULL
CONSTRAINT PK_Color_ColorId PRIMARY KEY (ColorId)
)
GO
-- Populating (adding rows to the) table Color
SET IDENTITY_INSERT dbo.Color ON
GO
INSERT INTO dbo.Color
(
ColorId
,Name
,Detail
)
VALUES
(
1 -- ID - INT Primary Key
,'Black' -- Name - varchar(50) NOT NULL
,'This is Black' -- Detail - varchar(200)
),
(
2 -- ID - INT Primary Key
,'White' -- Name - varchar(50) NOT NULL
,'This is White' -- Detail - varchar(200)
),
(
3 -- ID - INT Primary Key
,'Blue' -- Name - varchar(50) NOT NULL
,'This is Blue' -- Detail - varchar(200)
);
GO
SET IDENTITY_INSERT dbo.Color OFF
GO
-- Creating a table Watch
CREATE TABLE dbo.Watch
(
WatchId INT IDENTITY(1,1),
Name VARCHAR(50),
WatchTypeId INT,
ColorId INT,
Price DECIMAL(5,2),
CONSTRAINT PK_Watch_WatchId PRIMARY KEY (WatchId)
)
GO
-- Creating foreign key constraint on Watch table to get WatchTypeId values from WatchType table
ALTER TABLE dbo.Watch
ADD CONSTRAINT [FK_Watch_WatchType_WatchTypeId]
FOREIGN KEY ([WatchTypeId]) REFERENCES dbo.[WatchType] ([WatchTypeId]);
-- Creating foreign key constraint on Watch table to get ColorId values from Color table
ALTER TABLE dbo.Watch
ADD CONSTRAINT [FK_Watch_Color_ColorId]
FOREIGN KEY ([ColorId]) REFERENCES dbo.[Color] ([ColorId]);
-- Populating (adding rows to the) table Watch getting some columns values from reference tables
SET IDENTITY_INSERT WatchesDelSample.dbo.Watch ON
GO
INSERT WatchesDelSample.dbo.Watch(WatchId, Name, WatchTypeId, ColorId, Price) VALUES (1, 'Casio', 1, 1, 100.00)
INSERT WatchesDelSample.dbo.Watch(WatchId, Name, WatchTypeId, ColorId, Price) VALUES (2, 'Timex', 2, 2, 70.00)
GO
SET IDENTITY_INSERT WatchesDelSample.dbo.Watch OFF
GO
Бърза проверка на данните
Нека разгледаме всички редове на Часовник маса. За това изпълнете следния скрипт:
-- View the watch table data (rows)
SELECT w.WatchId
,w.Name
,w.WatchTypeId
,w.ColorId
,w.Price FROM dbo.Watch w
Резултатът е както следва:
Имайте предвид, че използвам dbForge Studio за SQL Server за тази демонстрация. Можете обаче да използвате SQL Server Management Studio (SSMS) за изпълнение на същите скриптове – резултатите ще бъдат същите.
Разбиране на идентификаторите (кодовете) зад колоните тип и цвят
Както можете да видите, има някои идентификатори под следните колони на таблицата за наблюдение:
- WatchTypeId
- ColorId
Тези колони получават стойности от референтните таблици, където са първоначално дефинирани. Таблицата за наблюдение се свързва с тези референтни таблици чрез ограничения на външния ключ.
Възникват три проблема с горния изход:
- Можем да видим WatchTypeId и ColorId, но не разбираме какво представляват.
- Ако разберем какво означават тези идентификатори, трябва постоянно да се връщаме към оригиналните им таблици, за да проверяваме.
- Най-важното е защо трябва да получаваме цвят и тип от други таблици?
Има причина да дефинираме Цвят (ColorId) и Тип (WatchTypeId) в други таблици. Трябва да гарантираме, че тези стойности остават последователни.
Ако първоначално не дефинираме стойността в референтните таблици, бихме могли да смесим думите, за да представим цвета или типа. Например, може да има и двете Сини и сини или Аналогов и Аналогов . За да избегнем подобен проблем, ние стандартизираме цветовете и видовете в референтните таблици. След това предаваме техните кодове на главната таблица.
Чрез присъединяване на таблицата за наблюдение с други референтни таблици, можем да извлечем стойностите зад тези кодове. Това е обичайна практика при разработването на бази данни.
Преглед на таблицата за наблюдение със стойности за тип и цвят зад идентификатори
Можем да видим действителното значение на кодовете зад Цвят и Тип, като изпълним следния скрипт:
-- View the watch table data (rows)
SELECT w.WatchId
,w.Name
,wt.Name AS WatchType
,c.Name AS ColorName
,w.Price FROM dbo.Watch w
INNER JOIN dbo.Color c ON c.ColorId=w.ColorId
INNER JOIN dbo.WatchType wt ON w.WatchTypeId = wt.WatchTypeId
Резултатът е следният:
Разбиране на архитектурата на базата данни
Нуждаем се от повече информация за архитектурата на тази база данни. Нашият фокус е върху това как таблиците се свързват една с друга.
Изображението по-горе демонстрира сценария на референтните таблици, които помагат на основната таблица да получава последователни данни. Това не е прост сценарий, особено за начинаещи, въпреки че е често срещан в много бази данни.
Изучаваме тази архитектура, защото трябва да разберем как да изтрием един или повече редове от някоя от горните таблици, когато са свързани по този начин.
Изтриване на ред от справочната (цветна) таблица
Можем ли да изтрием ред от справочната таблица или не? Нека разберем отговора.
Изтриваме първия ред от таблицата с цветове:
-- Deleting one row with color id 1 from the reference table color
DELETE FROM Color
WHERE ColorId = 1
Резултатът е следният:
Грешката означава, че не е разрешено да изтрием този ред, който искахме.
С други думи, не можем да изтрием ред от таблица, която се препраща от друга таблица.
Свързани редове срещу несвързани редове
Нека разделим редовете на референтната таблица в следните две категории:
- Свързани редове.
- Прекратени връзки.
Свързан ред е ред от референтна таблица, която се използва от друга таблица. Несвързан ред е ред от референтна таблица, за която друга таблица не се харесва.
Можем веднага да изтрием несвързани редове (записи) от референтна таблица.
Нашият по-ранен опит за изтриване на ред от таблицата с цветовете се провали, защото този ColorId (1) се използваше от основната таблица за наблюдение.
Преглед на справочната таблица (цвят)
Нека разгледаме референтната таблица, както следва:
-- View reference table Color
SELECT c.ColorId
,c.Name
,c.Detail FROM dbo.Color c
Резултатът е по-долу:
От предишните резултати знаем, че синият цвят (ColorId:3) не се използва от таблицата за наблюдение, тъй като все още няма син часовник, съхранен в таблицата.
Изтриване на несвързан ред от референтната (цветна) таблица
Изпълнете следния скрипт:
-- Deleting unlinked row with color id 3 from reference table Color
DELETE FROM Color
WHERE ColorId = 3 -- blue color
Успешно изтрихме реда и можем да го потвърдим, като прегледаме таблицата:
--View reference table Color after deleting the unlinked row
SELECT c.ColorId
,c.Name
,c.Detail FROM dbo.Color c
Резултатът е по-долу:
Показва, че редът, съдържащ синьото цветът е премахнат успешно от таблицата.
Съвет относно премахването на данни от справочната таблица
Не забравяйте, че не можете да изтриете запис (ред) от референтна таблица, ако се използва от друга таблица или група от таблици. Можете обаче да изтриете запис от същата (референтна) таблица, ако не се използва.
Изтриване на свързан ред от референтната (цветна) таблица
Ами ако искаме да премахнем ред от референтна таблица, знаейки, че предава референтните данни като цветове към друга таблица? С други думи, как да изтрием свързан ред от справочната таблица?
Първо, трябва да изтрием този ред от основната таблица, където е посочен.
Например, можем да изтрием цвета Бял от таблицата с цветове, както следва:
- Изтрийте всички редове от основната таблица (Гледайте), където цветът е бял (въз основа на идентификатора).
- Изтрийте реда от референтната таблица с цветове, където цветът е бял (въз основа на идентификатора).
Сега нека го разгледаме на практика.
Изтриване на всички редове, където цветът е бял, от основната таблица (Гледайте)
Нашата цел е да премахнем следите от бялото цвят от референтната и основната таблици.
Нека разгледаме данните, преди да ги изтрием. Искаме да проверим колко реда от основната таблица съдържат идентификатор на цвета 2 (бял):
-- View Watch table before deleting rows with white color (color id:2)
SELECT w.WatchId
,w.Name
,w.WatchTypeId
,w.ColorId
,w.Price FROM dbo.Watch w
WHERE w.ColorId=2 -- White Color
Резултатът е по-долу:
Сега изтрийте редовете с идентификатор на цвят 2, като изпълните следния T-SQL скрипт:
-- Deleting all the rows with color id 2 from main table Watch
DELETE FROM dbo.Watch
WHERE ColorId = 2 -- white color
Резултатът е както следва:
Вижте основната таблица, след като премахнете всички редове с бял цвят
Трябва да проверим главната таблица за редове, съдържащи идентификатор на цвят 2:
-- View the watch table data (rows)
SELECT w.WatchId
,w.Name
,wt.Name AS WatchType
,w.ColorId
,c.Name AS ColorName
,w.Price FROM dbo.Watch w
INNER JOIN dbo.Color c ON c.ColorId=w.ColorId
INNER JOIN dbo.WatchType wt ON w.WatchTypeId = wt.WatchTypeId
Както виждаме, записите за часовниците с бял цвят липсват. Това доказва, че успешно изтрихме всички тези редове.
Изтриване на по-рано свързан ред от справочната таблица (цвят)
След като премахнем посочените редове от основната таблица, можем да премахнем и по-рано свързания ред от референтната таблица. Факт е, че тази връзка вече не съществува.
Изпълнете следния скрипт срещу референтната таблица с цветове, за да изтриете реда с идентификатор на цвета 2 (бял):
-- View reference table before removing color id 1 (white)
SELECT c.ColorId
,c.Name
,c.Detail FROM dbo.Color c
-- Deleting one row with color id 2 from the reference table color
DELETE FROM Color
WHERE ColorId = 2 -- White Color
-- View reference table after removing color id 1 (white)
SELECT c.ColorId
,c.Name
,c.Detail FROM dbo.Color c
Резултатът е както следва:
Поздравления!
Научихме се как да премахнем един или повече редове от референтна таблица. Можем да го направим както ако редът се препраща, така и ако не. Освен това разгледахме изтриването на редове от основната таблица.
Съвет за изтриване на всички данни
Има друг израз на T-SQL, известен като Truncate Table – по-ефективно е за премахване на всички данни от таблица. Въпреки това, таблицата не трябва да се препраща другаде, защото тогава първо трябва да изтриете данните от основната таблица. Това е същото, което демонстрирахме в тази статия по-рано. След това ще приложим Отрязване изявление спрямо референтната таблица като последна стъпка.
Кодът е както следва:
-- Deleting all rows from the main table using Truncate
TRUNCATE TABLE dbo.Watch
Въпреки това, точно както с изявлението Delete, трябва да сте много внимателни с Truncate , или в крайна сметка изтривате всички данни от таблица.
Съвет
Изтриването на редове в сценарии в реално време най-вече ни помага или да премахнем нежелани данни (като оттеглени модели) от основната база данни или да архивираме данни и да ги съхраняваме в архивна база данни.
Неща за правене
Сега, когато можете да изтриете един или повече редове в леко напреднали сценарии, като например свързани таблици, опитайте следните неща, за да подобрите допълнително уменията си:
- Изтрийте типа аналогов часовник от референтната таблица WatchType въз основа на самоличността.
- Изтрийте всички редове от Цвят справочна таблица.
- Опитайте да нулирате примерната база данни и след това вижте колко бързо можете да изтриете всички данни от всички (референтни и основни) таблици.