Instrukcja DELETE była w konflikcie z ograniczeniem REFERENCE


11

Próbuję usunąć wszystkich użytkowników, ale pojawia się błąd:

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.

Zapytanie:

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

Wydaje się, że muszę użyć, on delete cascade;ale utknąłem.

Odpowiedzi:


18

Nie musisz używać kaskady przy usuwaniu. Ktoś (autor projektu schematu) upewnił się, że nie można usunąć osoby, do której nadal odwołuje się artykuł. Udało się, po prostu próbowałeś to zrobić i zostałeś zablokowany, uznanie dla projektanta.

Teraz idź i porozmawiaj z kimś, kto zaprojektował schemat i zna ograniczenia, i zapytaj go, jak prawidłowo usuwać rekordy, które próbujesz usunąć, w odpowiedniej kolejności i podejmując odpowiednie środki ostrożności, aby zachować spójność bazy danych.


9

Masz tutaj dwie prawdziwe opcje, możesz wyłączyć ograniczenia w tabeli. Zwykle nie jest to świetny pomysł, ponieważ możesz skończyć z złym stanem danych, jeśli zadzierasz z danymi odnoszącymi się do innych tabel, ale nie znasz pełnego zakresu schematu i może to odpowiadać Twoim celom:

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

Pamiętaj, aby ponownie włączyć ograniczenie po usunięciu za pomocą

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

Drugim wyborem byłoby usunięcie i ponowne dodanie ograniczenia z opcją ON DELETE CASCADE przy użyciu:

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

Na podstawie nazwy FK wygląda na to, że twoja tabela nadrzędna to M02ArticlePersons, a kolumna nadrzędna to M06Persons.

Jeśli nie jesteś autorem tego schematu, spróbuj zastanowić się, dlaczego ograniczenia mogą występować, i zrozum, że naruszenie ich w ten sposób może mieć niezamierzone skutki uboczne.


2

Tabela dbo.M02ArticlePersons kolumny M06PersonId znajduje się w innej tabeli. Dlatego przed usunięciem instrukcji wyłącz te relacje i spróbuj ponownie

poniżej służy do wyłączenia klucza obcego

 ALTER TABLE dbo.M02ArticlePersons NOCHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

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

i to ma to umożliwić

ALTER TABLE dbo.M02ArticlePersons CHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

Mam nadzieję, że to zadziała


2
okropna sugestia. NIGDY nie należy wyłączać ograniczenia FK, jeśli nie jesteś starszym dba (w takim przypadku nie napisałbyś powyższego pytania). Te ograniczenia mają na celu zapobieganie usuwaniu rekordów. Wyłączenie ich nie chcąc da złe dane w bazie danych. Zaleca się najgorszą, a nie dobrą praktykę.
HLGEM

1

Jest też inna opcja ręczna:

Możesz przejść do tabeli potomnej i usunąć wiersze potomne, do których odwołuje się klucz nadrzędny. Następnie możesz usunąć wiersz nadrzędny. Zasadniczo to robi usuwanie kaskadowe. W ten sposób nie musisz upuszczać / odtwarzać / zmieniać ograniczeń.


1

Ten mały kod pomoże każdej tabeli, z której chcesz usunąć rekordy. Dba również o integralność referencyjną ...

Poniższy kod wygeneruje instrukcje DELETE. Podaj po prostu 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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.