Заява DELETE суперечить обмеженню СПРАВКИ


11

Я намагаюся видалити всіх користувачів, але отримую помилку:

Msg 547, Level 16, State 0, Line 1
The DELETE statement conflicted with the REFERENCE constraint "FK_M02ArticlePersons_M06Persons". The conflict occurred in database "workdemo.no", table "dbo.M02ArticlePersons", column 'M06PersonId'.
The statement has been terminated.

Запит:

DELETE FROM [workdemo.no].[dbo].[M06Persons] 
WHERE ID > '13'
GO

Здається, мені потрібно користуватися, on delete cascade;але я застряг.

Відповіді:


18

Не потрібно використовувати каскад видалення. Хтось (автор дизайну схеми) переконався, що ви не можете видалити особу, на яку посилається стаття. Це вдалося, ти просто намагався це зробити і був заблокований, кудо дизайнеру.

Тепер ідіть і поговоріть з тим, хто розробив схему і знає обмеження, і запитайте його, як правильно видалити записи, які ви намагаєтесь видалити, у правильному порядку та вживши належних заходів безпеки, щоб зберегти базу даних.


9

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

ALTER TABLE [workdemo.no].[dbo].[M06Persons] NOCHECK CONSTRAINT [FK_M02ArticlePersons_M06Persons]

Не забудьте повернути обмеження після видалення за допомогою

ALTER TABLE [workdemo.no].[dbo].[M06Persons] WITH CHECK CHECK CONSTRAINT [FK_M02ArticlePersons_M06Persons]

Другим вибором буде скидання та повторне додавання обмежень за допомогою параметра ON DELETE CASCADE, використовуючи:

ALTER TABLE [workdemo.no].[dbo].[M06Persons] DROP CONSTRAINT [FK_M02ArticlePersons_M06Persons]

ALTER TABLE [workdemo.no].[dbo].[M06Persons] WITH NOCHECK ADD CONSTRAINT [FK_M02ArticlePersons_M06Persons] FOREIGN KEY(M06PersonId)
REFERENCES <parent table here> (<parent column here>)
ON DELETE CASCADE

Виходячи з вашого імені FK, схоже, ваша батьківська таблиця - M02ArticlePersons, а батьківський стовпець - M06Persons.

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


2

dbo.M02АртикулПерсональна таблиця стовпця M06PersonId відображається в іншій таблиці. Тому перед видаленням заяви вимкніть ці зв’язки та спробуйте ще раз

нижче - для відключення зовнішнього ключа

 ALTER TABLE dbo.M02ArticlePersons NOCHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

DELETE FROM [workdemo.no].[dbo].[M06Persons] 
  WHERE ID > '13'
GO

і це для того, щоб це ввімкнути

ALTER TABLE dbo.M02ArticlePersons CHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

Сподіваюся, це спрацює


2
жахлива пропозиція. НІКОЛИ не слід відключати обмеження у ФК, окрім того, ви старший dba (у якому випадку ви б не писали вище запитання). Ці обмеження існують, щоб не допустити видалення записів. Якщо вимкнути їх мимоволі, вони нададуть вам погані дані у вашій базі даних. Ви рекомендуєте найгіршу практику, а не хорошу.
HLGEM

1

Є й інший варіант вручну:

Можна перейти до дочірньої таблиці та видалити дочірні рядки, на які посилається батьківський ключ. Потім ви можете видалити батьківський рядок. Це по суті те, що робить каскадне видалення. Таким чином, вам не потрібно скидати / відтворювати / змінювати свої обмеження.


1

Цей маленький код допоможе для будь-якої таблиці, з якої потрібно видалити записи. Він також піклується про референтну цілісність ...

Нижче код генерує операції DELETE. Просто вкажіть схему.table_Name

Declare @sql1 varchar(max)
      , @ptn1 varchar(200)
      , @ctn1 varchar(200)
      , @ptn2 varchar(200)
      , @ctn2 varchar(200)
--
SET @ptn1 = ''
--
SET @ctn1 = ''
--
SET @ptn2 = ''
--
SET @ctn2 = ''
--
SELECT @sql1 = case when (@ptn1 <> OBJECT_NAME (f.referenced_object_id)) then
                         COALESCE( @sql1 + char(10), '') + 'DELETE' + char(10) + ' ' + OBJECT_NAME (f.referenced_object_id) + ' FROM ' + OBJECT_NAME(f.parent_object_id) + ', '+OBJECT_NAME (f.referenced_object_id) + char(10) +' WHERE ' + OBJECT_NAME(f.parent_object_id) + '.' + COL_NAME(fc.parent_object_id, fc.parent_column_id) +'='+OBJECT_NAME (f.referenced_object_id)+'.'+COL_NAME(fc.referenced_object_id, fc.referenced_column_id)
                    else
                         @sql1 + ' AND ' + OBJECT_NAME(f.parent_object_id) + '.' + COL_NAME(fc.parent_object_id, fc.parent_column_id) +'='+OBJECT_NAME (f.referenced_object_id)+'.'+COL_NAME(fc.referenced_object_id, fc.referenced_column_id)
                    end + char(10)
     , @ptn1 = OBJECT_NAME (f.referenced_object_id)
     , @ptn2  = object_name(f.parent_object_id)
FROM   sys.foreign_keys AS f
       INNER JOIN
       sys.foreign_key_columns AS fc ON f.object_id = fc.constraint_object_id
WHERE  f.parent_object_id = OBJECT_ID('dbo.M06Persons'); -- CHANGE here schema.table_name
--
print  '--Table Depended on ' + @ptn2 + char(10) + @sql1
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.