Як використовувати видалення каскаду за допомогою SQL Server?


332

У мене є 2 таблиці: T1 і T2, вони є існуючими таблицями з даними. Ми маємо відношення один до багатьох між T1 і T2. Як я можу змінити визначення таблиці, щоб виконати каскадне видалення на SQL Server, коли запис з T1 видалено, всі пов'язані записи в T2 також видалені.

Сторонне обмеження існує між ними. Я не хочу скидати таблиці або створювати тригер для видалення для T2. Наприклад, коли я видаляю співробітника, всі записи огляду теж повинні бути зникли.

T1 - Співробітник,

Employee ID      
Name
Status

T2 - Огляди продуктивності,

Employee ID - 2009 Review
Employee ID - 2010 Review

Відповіді:


362

Вам потрібно буде,

  • Скасуйте існуюче обмеження зовнішнього ключа,
  • Додайте новий із ON DELETE CASCADEувімкненою настройкою.

Щось на зразок:

ALTER TABLE dbo.T2
   DROP CONSTRAINT FK_T1_T2   -- or whatever it's called

ALTER TABLE dbo.T2
   ADD CONSTRAINT FK_T1_T2_Cascade
   FOREIGN KEY (EmployeeID) REFERENCES dbo.T1(EmployeeID) ON DELETE CASCADE

3
Ми з моєю командою просто це зробили. Нам довелося знизити свої обмеження та знову додати їх. Це працювало на нас.
Даніель Л. ВанДенБош

2
Як це на користь жорсткого видалення? М’яке видалення ніколи не матиме проблеми з обмеженнями. Мені здається зовсім протилежним.
Макс

2
@Maxx У режимі жорсткого видалення ви видаляєте один запис і не потрібно турбуватися про осиротілі регістри, тоді як при м'якому видаленні потрібно робити це вручну.
Роналду Арауджо Алвеш

319

Щоб додати "Видалити каскад" до наявного закордонного ключа в студії управління SQL Server:

Спочатку виберіть свій зовнішній ключ та відкрийте його у новому вікні запиту "DROP and Create To ..".

введіть тут опис зображення

Потім просто додайте ON DELETE CASCADEдо ADD CONSTRAINTкоманди:

н І натисніть кнопку "Виконати", щоб запустити цей запит.

До речі, щоб отримати список ваших іноземних ключів та побачити, які з них увімкнено "Каскад видалення", ви можете запустити цей сценарій:

SELECT 
   OBJECT_NAME(f.parent_object_id) AS 'Table name',
   COL_NAME(fc.parent_object_id,fc.parent_column_id) AS 'Field name',
   delete_referential_action_desc AS 'On Delete'
FROM sys.foreign_keys AS f,
     sys.foreign_key_columns AS fc,
     sys.tables t 
WHERE f.OBJECT_ID = fc.constraint_object_id
AND t.OBJECT_ID = fc.referenced_object_id
ORDER BY 1

І якщо ви коли-небудь виявите, що ви не можете DROPвстановити певну таблицю через обмеження зовнішнього ключа, але ви не можете розібратися, який FK викликає проблему, тоді ви можете запустити цю команду:

sp_help 'TableName'

SQL у цій статті перелічує всі FK, на які посилається певна таблиця.

Сподіваюся, що все це допомагає.

Вибачення за довгий палець. Я просто намагався зробити крапку.


163

Це можна зробити за допомогою SQL Server Management Studio.

→ Клацніть правою кнопкою миші дизайн таблиці та перейдіть до «Відносини» та виберіть зовнішню клавішу на лівій панелі та на правій панелі, розгорніть меню «ВСТАВКА та ОНОВЛЕННЯ специфікацій» та виберіть «Каскад» як Видалити правило.

Студія управління SQL Server


привіт, яка різниця між 4-ма, чи робить поворот каскаду, щоб полегшити видалення всіх даних у таблиці. Як я можу переглянути всі залежності клавішу / Рк на цій таблиці, не з цієї таблиці. Навіть після видалення всіх ФК я все одно отримую помилку
вересня

@aggie - Ви можете перевірити залежності: - Клацніть правою кнопкою миші таблицю -> "Перегляд залежностей". Також сервер sql дасть вам детальну помилку з назвою таблиці та назвою стовпців на кшталт цього "Виписка DELETE суперечить обмеженню REFERENCE" FK_Child1_Parent1 ". Конфлікт стався в базі даних "TESTDB", таблиці "dbo.Child1", стовпці "Parent1ID". "
Palanikumar

@aggie - Також 4-й випадок "Встановити за замовчуванням", Ви повинні встановити обмеження за замовчуванням у стовпці Іноземний ключ, коли ми видаляємо батьківський, тоді значення за замовчуванням буде замінено у дочірніх таблицях. (Примітка. Значення за замовчуванням має відповідати батьківській таблиці.) Для отримання додаткової інформації відвідайте mssqltips.com/sqlservertip/2365/…
Palanikumar

Це дуже корисно. Цікаво, чому не існує Правила вставки? Іншими словами, коли я додаю рядок до T1, я хочу, щоб відповідний запис у T2 був створений автоматично.
Роберт М.

@RobertM. Тому що це не має сенсу. Як би знати, які значення INSERT? Можливо, вам вдасться використовувати тригери INSERT для генерації дитячих рядків, спробуйте це дослідити.
Ден Бешард

47

Використовуйте щось подібне

ALTER TABLE T2
ADD CONSTRAINT fk_employee
FOREIGN KEY (employeeID)
REFERENCES T1 (employeeID)
ON DELETE CASCADE;

Заповніть правильні назви стовпців, і вам слід встановити. Як правильно вказано mark_s, якщо у вас вже є обмеження на зовнішній ключ, можливо, вам потрібно спочатку видалити старий, а потім створити новий.


41
@marc_s - насправді ви можете додати другий зовнішній ключ проти абсолютно однакових стовпців з обох сторін, і він буде працювати правильно. Якщо ви працюєте у виробничих умовах без простоїв, можливо, краще представити новий ФК з каскадом, а потім скинути старіший ФК, а не залишати вікно на столі, коли ФК немає. (Щойно перевірено на SQL 2008)
Damien_The_Unbeliever

Це вірно. Я спробував це, і це працює. Не потрібно скасовувати перші обмеження іноземних ключів. Дякую за відповідь.
Bichvan Nguyen

15

Спочатку ввімкніть властивість ONCascade:

1.Допустити існуюче обмеження зовнішнього ключа

2.Додайте новий з увімкненою настройкою ON DELETE CASCADE

Наприклад:

IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.Response'))
 BEGIN 

ALTER TABLE [dbo].[Response] DROP CONSTRAINT [FK_Response_Request]  

ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END

ELSE

 BEGIN 
 ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END

Друге, щоб вимкнути властивість ONCascade:

1.Допустити існуюче обмеження зовнішнього ключа

2.Додайте нове з увімкненим налаштуванням ON DELETE NO ACTION

Наприклад:

IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.Response'))
 BEGIN 
ALTER TABLE [dbo].[Response] DROP CONSTRAINT [FK_Response_Request]  

ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END

ELSE

 BEGIN 
 ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE NO ACTION 
END

15

ON DELETE CASCADE
Він визначає, що дочірні дані видаляються при видаленні батьківських даних.

CREATE TABLE products
( product_id INT PRIMARY KEY,
  product_name VARCHAR(50) NOT NULL,
  category VARCHAR(25)
);

CREATE TABLE inventory
( inventory_id INT PRIMARY KEY,
  product_id INT NOT NULL,
  quantity INT,
  min_level INT,
  max_level INT,
  CONSTRAINT fk_inv_product_id
    FOREIGN KEY (product_id)
    REFERENCES products (product_id)
    ON DELETE CASCADE
);

Для цього зовнішнього ключа ми вказали ON DELETE CASCADEпункт, який повідомляє SQL Server видаляти відповідні записи в дочірній таблиці, коли дані з батьківської таблиці видаляються. Отже, у цьому прикладі, якщо значення product_id буде видалено з таблиці продуктів, відповідні записи в таблиці інвентаризації, які використовують цей product_id, також будуть видалені.


-2

Якщо співвідношення один до багатьох є від T1 до T2, то воно не представляє функцію і тому не може бути використане для виведення або висновку зворотної функції, яка гарантує, що отримане значення T2 не опускає кортежі T1, приєднані до T2, дедуктивно дійсні , тому що немає дедуктивно допустимої зворотної функції. (Представлення функцій було призначенням первинних ключів.) Відповідь у SQL думаю: так, ви можете це зробити. Відповідь у реляційній думці - ні, ви не можете цього зробити. Див. Пункти двозначності в Codd 1970. Відносини повинні були бути багато-на-один від T1 до T2.


-10

Я думаю, що ви не можете просто видалити властивість таблиць, а якщо це фактичні виробничі дані, просто видаліть вміст, який не впливає на схему таблиці.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.