L'istruzione DELETE è in conflitto con il vincolo REFERENCE


11

Sto cercando di eliminare tutti gli utenti ma ricevo l'errore:

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 domanda:

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

Sembra che devo usare on delete cascade;ma sono bloccato.

Risposte:


18

Non è necessario utilizzare la cascata on delete. Qualcuno (l'autore della progettazione dello schema) si era assicurato che non fosse possibile eliminare una persona a cui fa ancora riferimento un articolo. Ci è riuscito, stavi solo cercando di farlo ed è stato bloccato, complimenti al designer.

Ora vai a parlare con qualcuno che ha progettato lo schema e conosce i vincoli e chiedigli come eliminare correttamente i record che stai cercando di eliminare, nell'ordine corretto e prendendo le precauzioni appropriate per mantenere coerente il database.


9

Hai due scelte reali qui, puoi disabilitare i vincoli sulla tabella. Questo di solito non è una grande idea in quanto puoi finire con una cattiva condizione dei dati se stai scherzando con dati che si riferiscono ad altre tabelle, ma non conosci l'intera estensione del tuo schema e potrebbe soddisfare i tuoi scopi:

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

Ricorda di riattivare il vincolo dopo l'eliminazione con

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

La seconda scelta sarebbe quella di eliminare e aggiungere nuovamente il vincolo con l'opzione 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

In base al nome FK sembra che la tabella padre sia M02ArticlePersons e la colonna padre sia M06Persons.

Se non hai creato questo schema, prova a considerare il motivo per cui i vincoli potrebbero essere presenti e capire che violarli in questo modo può avere effetti collaterali indesiderati.


2

La tabella dbo.M02ArticlePersons della colonna M06PersonId è di nuovo riferimento in un'altra tabella. Quindi, prima di eliminare l'istruzione, disabilitare queste relazioni e riprovare

di seguito è per sbloccare la chiave esterna

 ALTER TABLE dbo.M02ArticlePersons NOCHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

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

e questo per abilitarlo

ALTER TABLE dbo.M02ArticlePersons CHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

Spero che questo funzioni


2
suggerimento orribile. Non devi MAI disabilitare un vincolo FK a meno che tu non sia un senior dba (nel qual caso non avresti scritto la domanda sopra). Tali vincoli sono lì per impedirti di eliminare i record. Disabilitarli volenti o nolenti ti darà dati cattivi nel tuo database. Stai raccomandando una delle peggiori pratiche, non una buona.
HLGEM,

1

C'è anche un'altra opzione manuale:

È possibile accedere alla tabella figlio ed eliminare le righe figlio a cui fa riferimento la chiave principale. Quindi è possibile eliminare la riga principale. Questo è essenzialmente ciò che fa l'eliminazione in cascata. In questo modo, non è necessario eliminare / ricreare / modificare i vincoli.


1

Questo piccolo codice aiuterà per qualsiasi tabella da cui si desidera eliminare i record. Si occupa anche dell'integrità referenziale ...

Il codice seguente genererà le istruzioni DELETE. Basta specificare lo 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.