Как использовать каскадное удаление с 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
marc_s
источник
3
Моя команда и я только что сделали это. Нам пришлось отбросить наши ограничения и заново добавить их. Это сработало для нас.
Даниэль Л. ВанДенБош
2
Как это в пользу жесткого удаления? Мягкое удаление никогда не будет иметь проблемы с ограничением. Кажется, совсем наоборот.
Maxx
2
@Maxx При жестком удалении вы удаляете одну запись, и вам не нужно беспокоиться о потерянных регистрах, тогда как при мягком удалении это нужно делать вручную.
Роналду Араужо Алвес
319

Чтобы добавить «Каскадное удаление» к существующему внешнему ключу в SQL Server Management Studio:

Сначала выберите ваш внешний ключ и откройте его «DROP and Create To ..» в новом окне запроса.

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

Затем просто добавьте ON DELETE CASCADEв ADD CONSTRAINTкоманду:

N И нажмите кнопку «Выполнить», чтобы выполнить этот запрос.

Кстати, чтобы получить список ваших внешних ключей и увидеть, в каких из них включена функция «Каскадное удаление», вы можете запустить этот скрипт:

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 Management Studio

Palanikumar
источник
Привет, в чем разница между 4, делает ли каскад включение легко удалить все данные в таблице. Как я могу просмотреть все зависимости / ключи FK в этой таблице, а не из этой таблицы. Даже после удаления всех FK я все еще получаю ошибку
aggie
@aggie - Вы можете проверить зависимости, щелкнув правой кнопкой мыши таблицу -> «Просмотр зависимостей». Кроме того, сервер sql выдаст вам подробную ошибку с именем таблицы и именем столбца, например «Оператор DELETE конфликтует с ограничением REFERENCE« FK_Child1_Parent1 ». Конфликт произошел в базе данных «TESTDB», таблице «dbo.Child1», столбце «Parent1ID». "
Паланикумар
@aggie - Также в 4-м случае «Установить значение по умолчанию» необходимо установить ограничение по умолчанию в столбце «Внешний ключ», при удалении родителя значение по умолчанию будет заменено в дочерних таблицах. (Примечание: значение по умолчанию должно совпадать с родительской таблицей.) Для получения дополнительной информации посетите mssqltips.com/sqlservertip/2365/…
Palanikumar
Это очень полезно. Интересно, а почему нет правила вставки? Другими словами, когда я добавляю строку в T1, я хочу, чтобы соответствующая запись в T2 создавалась автоматически.
Роберт М.
@RobertM. Потому что это не имеет смысла. Как бы он знал, какие значения для вставки? Вы можете использовать триггеры INSERT для генерации дочерних строк, попробуйте исследовать это.
Дэн
47

Используйте что-то вроде

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

Введите правильные имена столбцов, и вы должны быть установлены. Как правильно указано mark_s, если у вас уже есть ограничение внешнего ключа, вам, возможно, потребуется сначала удалить старый, а затем создать новый.

Hyperboreus
источник
41
@marc_s - фактически вы можете добавить второй внешний ключ к точно таким же столбцам с обеих сторон, и он будет работать правильно. Если вы работаете в производственной среде без простоя, может быть предпочтительнее ввести новый FK с каскадом, а затем отбросить старый FK, а не оставлять окно на столе, когда FK отсутствует. (Только что протестировано на SQL 2008)
Damien_The_Unbeliever
Это верно. Я попробовал это, и это работает. Нет необходимости удалять первые ограничения внешнего ключа. Спасибо за ответ.
Бичван Нгуен
15

Свойство First To Enable 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

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

Apple Lover
источник