DELETE deyimi REFERENCE kısıtlamasıyla çakıştı


11

Tüm kullanıcıları silmeye çalışıyorum ama hatayı alıyorum:

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.

Sorgu:

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

Kullanmam gerekiyor gibi görünüyor on delete cascade;ama takıldım.

Yanıtlar:


18

On delete kaskadını kullanmanıza gerek yoktur. Birisi (şema tasarım yazarı), hala bir makalenin başvurduğu bir kişiyi silemeyeceğinizden emin olmuştu. Başarılı oldu, sadece bunu yapmaya çalışıyordunuz ve engellendi, tasarımcıya şuralar.

Şimdi gidip şemayı tasarlayan ve kısıtlamaları bilen biriyle konuşun ve silmeye çalıştığınız kayıtları doğru sırayla nasıl doğru bir şekilde silebileceğini ve veritabanını tutarlı tutmak için gerekli önlemleri aldığını sorun.


9

Burada iki gerçek seçeneğiniz var, tablodaki kısıtlamaları devre dışı bırakabilirsiniz. Bu genellikle harika bir fikir değildir, çünkü diğer tablolarla ilgili verilerle uğraşıyorsanız, ancak şemanızın tam boyutunu bilmediğiniz ve amaçlarınıza uygun olabileceği için kötü bir veri durumu ile sonuçlanabilirsiniz.

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

Silme işleminden sonra kısıtlamayı tekrar açmayı unutmayın.

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

İkinci seçenek, kısıtlamayı ON DELETE CASCADE seçeneğiyle bırakmak ve yeniden eklemek olacaktır:

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

FK adınıza göre üst tablonuz M02ArticlePersons ve üst sütun M06Persons gibi görünüyor.

Bu şemayı yazmadıysanız, lütfen kısıtlamaların neden mevcut olabileceğini düşünmeye çalışın ve bu şekilde ihlal etmenin istenmeyen yan etkileri olabileceğini anlayın.


2

m06PersonId sütununun dbo.M02ArticlePersons tablosu başka bir tabloya yeniden doldurulur. Yani ifadeyi silmeden önce bu ilişkileri devre dışı bırakın ve tekrar deneyin

aşağıda yabancı anahtarı devre dışı bırakmak içindir

 ALTER TABLE dbo.M02ArticlePersons NOCHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

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

ve bu onu etkinleştirmek için

ALTER TABLE dbo.M02ArticlePersons CHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

Umarım bu işe yarar


2
korkunç öneri. Kıdemli bir dba olduğunuzda bir FK kısıtlamasını ASLA devre dışı bırakmamalısınız (bu durumda yukarıdaki soruyu yazmazsınız). Bu kısıtlamalar, kayıtları silmenizi önlemek için vardır. Onları willy nilly devre dışı bırakmak veritabanınızda kötü veri verecektir. İyi bir uygulama değil, en kötü uygulamayı tavsiye ediyorsunuz.
HLGEM

1

Başka bir manuel seçenek daha var:

Alt tabloya gidebilir ve üst anahtar tarafından başvurulan alt satırları silebilirsiniz. Ardından üst satırı silebilirsiniz. Bu temelde basamaklı silme işleminin yaptığı şeydir. Bu şekilde, kısıtlamalarınızı düşürmeniz / yeniden oluşturmanız / değiştirmeniz gerekmez.


1

Bu küçük kod, kayıtları silmek istediğiniz herhangi bir tablo için yardımcı olacaktır. Referans bütünlüğüne de dikkat eder ...

Aşağıdaki kod DELETE ifadeleri oluşturur .. Sadece schema.table_Name belirtin

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.