Die DELETE-Anweisung stand in Konflikt mit der REFERENCE-Einschränkung

10

Ich versuche alle Benutzer zu löschen, erhalte aber den Fehler:

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.

Die Abfrage:

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

Scheint, ich muss verwenden, on delete cascade;aber ich stecke fest.

Dunkeler Zauberer
quelle

Antworten:

18

Sie müssen die Kaskade zum Löschen nicht verwenden. Jemand (der Autor des Schemadesigns) hat sichergestellt, dass Sie eine Person nicht löschen können, auf die noch in einem Artikel verwiesen wird. Es ist gelungen, Sie haben nur versucht, dies zu tun, und wurden blockiert, ein großes Lob an den Designer.

Sprechen Sie jetzt mit jemandem, der das Schema entworfen hat und die Einschränkungen kennt, und fragen Sie ihn, wie die zu löschenden Datensätze in der richtigen Reihenfolge und mit den richtigen Vorsichtsmaßnahmen, um die Datenbank konsistent zu halten, ordnungsgemäß gelöscht werden.

Remus Rusanu
quelle
9

Sie haben hier zwei echte Möglichkeiten: Sie können Einschränkungen für die Tabelle deaktivieren. Dies ist normalerweise keine gute Idee, da Sie möglicherweise einen schlechten Datenzustand haben, wenn Sie mit Daten herumspielen, die sich auf andere Tabellen beziehen, aber nicht den vollen Umfang Ihres Schemas kennen und es möglicherweise Ihren Zwecken entspricht:

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

Denken Sie daran, die Einschränkung nach dem Löschen mit wieder zu aktivieren

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

Die zweite Möglichkeit wäre, die Einschränkung mit der Option ON DELETE CASCADE zu löschen und erneut hinzuzufügen, indem Sie Folgendes verwenden:

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

Basierend auf Ihrem FK-Namen sieht es so aus, als ob Ihre übergeordnete Tabelle M02ArticlePersons und die übergeordnete Spalte M06Persons ist.

Wenn Sie dieses Schema nicht erstellt haben, versuchen Sie bitte zu überlegen, warum die Einschränkungen vorhanden sein können, und verstehen Sie, dass eine Verletzung auf diese Weise unbeabsichtigte Nebenwirkungen haben kann.

Ahrotahntee
quelle
2

Die Tabelle dbo.M02ArticlePersons der Spalte M06PersonId wird in einer anderen Tabelle angezeigt. Deaktivieren Sie diese Beziehungen, bevor Sie die Anweisung löschen, und versuchen Sie es erneut

unten ist zum Deaktivieren des Fremdschlüssels

 ALTER TABLE dbo.M02ArticlePersons NOCHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

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

und dies soll es ermöglichen

ALTER TABLE dbo.M02ArticlePersons CHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

Hoffe das wird funktionieren

Navin 431
quelle
2
schrecklicher Vorschlag. Sie sollten NIEMALS eine FK-Einschränkung deaktivieren, es sei denn, Sie sind ein Senior-DBA (in diesem Fall hätten Sie die obige Frage nicht geschrieben). Diese Einschränkungen verhindern, dass Sie die Datensätze löschen. Wenn Sie sie wohl oder übel deaktivieren, erhalten Sie schlechte Daten in Ihrer Datenbank. Sie empfehlen eine schlechteste und keine gute Praxis.
HLGEM
1

Es gibt noch eine andere manuelle Option:

Sie können zur untergeordneten Tabelle gehen und die untergeordneten Zeilen löschen, auf die der übergeordnete Schlüssel verweist. Dann können Sie die übergeordnete Zeile löschen. Dies ist im Wesentlichen das, was das Löschen von Kaskaden bewirkt. Auf diese Weise müssen Sie Ihre Einschränkungen nicht löschen / neu erstellen / ändern.

Stanley Johns
quelle
1

Dieser kleine Code hilft bei jeder Tabelle, aus der Sie Datensätze löschen möchten. Es kümmert sich auch um die referenzielle Integrität ...

Der folgende Code generiert DELETE-Anweisungen. Geben Sie einfach den schema.table_Name an

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
quelle