Оператор DELETE конфликтует с ограничением REFERENCE

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;но я застрял.

Darkmage
источник

Ответы:

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.

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

Ahrotahntee
источник
2

Таблица dbo.M02ArticlePersons столбца 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

Надеюсь это сработает

Навин 431
источник
2
ужасное предложение. Вы НИКОГДА не должны отключать ограничение FK, если вы не являетесь старшим dba (в этом случае вы не написали бы вопрос выше). Эти ограничения существуют, чтобы помешать вам удалить записи. Отключив их, вы получите плохие данные в вашей базе данных. Вы рекомендуете худшую практику, а не хорошую.
HLGEM
1

Также есть еще один ручной вариант:

Вы можете перейти к дочерней таблице и удалить дочерние строки, на которые ссылается родительский ключ. Затем вы можете удалить родительский ряд. По сути, это то, что делает каскадное удаление. Таким образом, вам не нужно удалять / пересоздавать / изменять свои ограничения.

StanleyJohns
источник
1

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

Ниже код будет генерировать операторы DELETE. Просто укажите schema.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
Кин Шах
источник