L'instruction DELETE est en conflit avec la contrainte REFERENCE

11

J'essaie de supprimer tous les utilisateurs mais j'obtiens l'erreur:

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.

La requête:

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

Semble que je dois utiliser on delete cascade;mais je suis coincé.

Mage sombre
la source

Réponses:

18

Vous n'avez pas besoin d'utiliser la cascade de suppression. Quelqu'un (l'auteur de la conception du schéma) s'est assuré que vous ne pouvez pas supprimer une personne qui est toujours référencée par un article. Cela a réussi, vous essayiez simplement de le faire et a été bloqué, bravo au designer.

Maintenant, allez parler à quelqu'un qui a conçu le schéma et connaît les contraintes et demandez-lui comment supprimer correctement les enregistrements que vous essayez de supprimer, dans le bon ordre et en prenant les précautions appropriées pour maintenir la base de données cohérente.

Remus Rusanu
la source
9

Vous avez ici deux choix réels, vous pouvez désactiver les contraintes sur la table. Ce n'est généralement pas une bonne idée car vous pouvez vous retrouver avec une mauvaise condition de données si vous jouez avec des données qui se rapportent à d'autres tables, mais ne connaissez pas l'étendue complète de votre schéma et cela peut convenir à vos besoins:

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

N'oubliez pas de réactiver la contrainte après la suppression avec

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

Le deuxième choix serait de supprimer et de rajouter la contrainte avec l'option ON DELETE CASCADE en utilisant:

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

En fonction de votre nom FK, il semble que votre table parent soit M02ArticlePersons et que la colonne parent soit M06Persons.

Si vous n'avez pas créé ce schéma, essayez de déterminer pourquoi les contraintes peuvent être présentes et comprenez que les violer de cette manière peut avoir des effets secondaires involontaires.

Ahrotahntee
la source
2

La table dbo.M02ArticlePersons de la colonne M06PersonId est référencée dans une autre table. Donc, avant de supprimer l'instruction, désactivez ces relations et réessayez

ci-dessous est pour disbling la clé étrangère

 ALTER TABLE dbo.M02ArticlePersons NOCHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

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

et c'est pour lui permettre

ALTER TABLE dbo.M02ArticlePersons CHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

J'espère que cela fonctionnera

Navin 431
la source
2
horrible suggestion. Vous ne devez JAMAIS désactiver une contrainte FK si vous n'êtes pas un dba senior (auquel cas vous n'auriez pas écrit la question ci-dessus). Ces contraintes sont là pour vous empêcher de supprimer les enregistrements. Les désactiver volontairement vous donnera de mauvaises données dans votre base de données. Vous recommandez une pire pratique, pas une bonne.
HLGEM
1

Il existe également une autre option manuelle:

Vous pouvez accéder à la table enfant et supprimer les lignes enfant référencées par la clé parent. Ensuite, vous pouvez supprimer la ligne parent. C'est essentiellement ce que fait la suppression en cascade. De cette façon, vous n'avez pas à supprimer / recréer / modifier vos contraintes.

StanleyJohns
la source
1

Ce petit code vous aidera pour toute table dont vous souhaitez supprimer les enregistrements. Il prend également en charge l'intégrité référentielle ...

Le code ci-dessous générera des instructions DELETE. Spécifiez simplement le nom du schéma.

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
la source