Pernyataan DELETE bertentangan dengan batasan REFERENSI

11

Saya mencoba untuk menghapus semua pengguna tetapi mendapatkan kesalahan:

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.

Kueri:

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

Sepertinya saya perlu menggunakan on delete cascade;tapi saya macet.

Darkmage
sumber

Jawaban:

18

Anda tidak perlu menggunakan kaskade penghapusan. Seseorang (penulis desain skema) telah memastikan Anda tidak dapat menghapus orang yang masih dirujuk oleh artikel. Berhasil, Anda hanya mencoba melakukan ini dan diblokir, pujian kepada desainer.

Sekarang pergi dan berbicara dengan seseorang yang merancang skema dan mengetahui kendala dan bertanya kepadanya bagaimana cara menghapus catatan yang Anda coba hapus, dalam urutan yang benar dan mengambil tindakan pencegahan yang tepat untuk menjaga database konsisten.

Remus Rusanu
sumber
9

Anda memiliki dua pilihan nyata di sini, Anda dapat menonaktifkan batasan di atas meja. Ini biasanya bukan ide yang bagus karena Anda bisa berakhir dengan kondisi data yang buruk jika Anda mengacaukan data yang terkait dengan tabel lain, tetapi tidak tahu sepenuhnya skema Anda dan mungkin sesuai dengan tujuan Anda:

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

Ingatlah untuk mengaktifkan kembali kendala setelah penghapusan dengan

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

Pilihan kedua adalah dengan menjatuhkan dan menambahkan kembali kendala dengan opsi ON DELETE CASCADE menggunakan:

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

Berdasarkan nama FK Anda, sepertinya tabel induk Anda adalah M02ArticlePersons dan kolom induknya adalah M06Persons.

Jika Anda tidak membuat skema ini, cobalah untuk mempertimbangkan mengapa kendala mungkin ada, dan pahami bahwa melanggarnya dengan cara ini mungkin memiliki efek samping yang tidak diinginkan.

Ahrotahntee
sumber
2

dbo.M02ArticlePersons tabel kolom M06PersonId direferensikan di tabel lain. Jadi sebelum menghapus pernyataan, nonaktifkan hubungan ini dan coba lagi

di bawah ini untuk melepaskan kunci asing

 ALTER TABLE dbo.M02ArticlePersons NOCHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

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

dan ini untuk mengaktifkannya

ALTER TABLE dbo.M02ArticlePersons CHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

Semoga ini berhasil

Navin 431
sumber
2
saran yang mengerikan. Anda harus TIDAK PERNAH menonaktifkan kendala FK kecuali Anda adalah dba senior (jika Anda tidak akan menulis pertanyaan di atas). Kendala itu ada untuk mencegah Anda menghapus catatan. Menonaktifkan mereka mau tidak mau akan memberi Anda data buruk di database Anda. Anda merekomendasikan praktik terburuk bukan yang baik.
HLGEM
1

Ada opsi manual lain juga:

Anda bisa pergi ke tabel anak dan menghapus baris anak yang dirujuk oleh kunci induk. Kemudian Anda dapat menghapus baris induk. Ini pada dasarnya adalah apa yang dilakukan oleh penghapusan kaskade. Dengan cara ini, Anda tidak perlu menjatuhkan / membuat ulang / mengubah batasan Anda.

StanleyJohns
sumber
1

Kode kecil ini akan membantu untuk setiap tabel yang ingin Anda hapus catatannya. Itu merawat integritas referensial juga ...

Kode di bawah ini akan menghasilkan pernyataan DELETE .. Cukup tentukan 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
sumber