A instrução DELETE entra em conflito com a restrição REFERENCE

11

Estou tentando excluir todos os usuários, mas obtendo o erro:

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.

A pergunta:

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

Parece que preciso usar, on delete cascade;mas estou preso.

Darkmage
fonte

Respostas:

18

Você não precisa usar a cascata on delete. Alguém (o autor do design do esquema) certificou-se de que não é possível excluir uma pessoa que ainda é referenciada por um artigo. Foi bem-sucedido, você estava apenas tentando fazer isso e foi bloqueado, parabéns ao designer.

Agora vá e converse com alguém que projetou o esquema e conhece as restrições e pergunte a ele como excluir corretamente os registros que você está tentando excluir, na ordem correta e tomando as devidas precauções para manter o banco de dados consistente.

Remus Rusanu
fonte
9

Você tem duas opções reais aqui, é possível desativar as restrições na tabela. Isso geralmente não é uma ótima idéia, pois você pode acabar com uma condição de dados incorreta se estiver mexendo com dados relacionados a outras tabelas, mas não conhece toda a extensão do seu esquema e pode atender aos seus propósitos:

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

Lembre-se de ativar a restrição novamente após a exclusão com

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

A segunda opção seria descartar e adicionar novamente a restrição com a opção ON DELETE CASCADE usando:

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

Com base no seu nome FK, parece que sua tabela pai é M02ArticlePersons e a coluna pai é M06Persons.

Se você não criou este esquema, tente considerar por que as restrições podem estar presentes e entenda que violá-las dessa maneira pode ter efeitos colaterais indesejados.

Ahrotahntee
fonte
2

A tabela dbo.M02ArticlePersons da coluna M06PersonId é referenciada em outra tabela. Portanto, antes de excluir a instrução, desative esses relacionamentos e tente novamente

abaixo é para desativar a chave estrangeira

 ALTER TABLE dbo.M02ArticlePersons NOCHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

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

e isso é para habilitá-lo

ALTER TABLE dbo.M02ArticlePersons CHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

Espero que isso funcione

Navin 431
fonte
2
sugestão horrível. NUNCA desative uma restrição FK se não for um dba sênior (nesse caso, você não teria escrito a pergunta acima). Essas restrições existem para impedir que você exclua os registros. Desabilitá-los, quer ou não, fornecerá dados ruins no seu banco de dados. Você está recomendando uma prática pior e não uma boa.
HLGEM
1

Há outra opção manual também:

Você pode ir para a tabela filho e excluir as linhas filho referenciadas pela chave pai. Então você pode excluir a linha pai. Isso é essencialmente o que a exclusão em cascata faz. Dessa forma, você não precisa eliminar / recriar / alterar suas restrições.

StanleyJohns
fonte
1

Esse pequeno código ajudará em qualquer tabela da qual você deseja excluir registros. Ele cuida da integridade referencial também ...

O código abaixo irá gerar instruções DELETE. Basta especificar o 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
Kin Shah
fonte