dataiotech Labs
dbaguidedbaguideDBAdataxtoolsdataopsphere
Home/Hata Teşhis Kütüphanesi/sqlserver-547-foreign-key-constraint
SQL Server
SQL Server 2025 / 2022Veri Bütünlüğü & Kısıtlar
6 dk okuma
The INSERT statement conflicted with the FOREIGN KEY constraint

SQL Server Error 547 — Foreign Key Neden Reddediyor, Hangi Satır Suçlu?

547 hatasında yetim satırları bulma, NOCHECK ile WITH CHECK arasındaki güven farkı ve toplu yüklemede doğru sıra.

İnceleyen:Principal Database Architect
Test Edilen Sürümler: SQL Server 2025 (17.0 CU10 KB5125471) & 2022 (16.0 CU14)

Operasyonel Doğrulama & Güvenilirlik Standardı

Son Teknik İnceleme: 29 Ekim 2026
Test Edilen SürümlerSQL Server 2025 (17.0 CU10 KB5125471) & 2022 (16.0 CU14)
Gerekli YetkiALTER TABLE ve sys.foreign_keys görüntüleme yetkisi
Risk Seviyesi
MediumWITH NOCHECK ile kısıt açılması is_not_trusted=1 bırakır; sorgu iyileştiricisi kısıtı yoksayar ve planlar bozulur
Beklenen Çıktıis_not_trusted = 0 durumuna getirilmiş ve yetim satırları temizlenmiş Foreign Key kısıtı
Geri Dönüş (Rollback) Planı:Geçici eklenen kısıtları kaldırma ve yetim kayıtları orijinal durumuna geri getirme
Microsoft Learn: SQL Server Foreign Key Constraints
İlk 60 Saniye Teşhis Protokolü:

Hata mesajı semptomdur, kök neden değildir. Sunucuyu yeniden başlatmadan veya rastgele ayar değiştirmeden önce aşağıdaki "Nedeni ayırt eden tek sorgu"yu çalıştırarak gerçek senaryoyu netleştirin.

▸Belirti

plaintext
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Siparis_Musteri". The conflict occurred in database "app", table "dbo.Musteri", column 'Id'.

Aynı 547 hata numarası iki farklı işlemde ortaya çıkar ve mesajın ilk ifadesi kök nedeni ayırt eder:

  • •`The INSERT statement...` → Çocuk (child) tabloya, ebeveyn (parent) tabloda karşılığı olmayan bir yabancı anahtar yazılmaya çalışılıyor.
  • •`The DELETE statement conflicted with the REFERENCE constraint...` → Ebeveyn tablodan bir satır silinmek isteniyor ancak çocuk tabloda ona bağlı kayıtlar mevcut.

▸Adım Adım Teşhis ve Çözüm

1. Kısıtın Tanımını ve Güven Durumunu Doğrulayın

sql
SELECT fk.name AS kisit, OBJECT_NAME(fk.parent_object_id) AS cocuk_tablo, COL_NAME(fkc.parent_object_id, fkc.parent_column_id) AS cocuk_kolon, OBJECT_NAME(fk.referenced_object_id) AS ebeveyn_tablo, COL_NAME(fkc.referenced_object_id, fkc.referenced_column_id) AS ebeveyn_kolon, fk.is_disabled, fk.is_not_trusted FROM sys.foreign_keys fk JOIN sys.foreign_key_columns fkc ON fkc.constraint_object_id = fk.object_id WHERE fk.name = 'FK_Siparis_Musteri';
ÖNEMLİ
is_not_trusted = 1 Tehlikesi: Kısıt aktif olsa bile SQL Server'ın mevcut veriye güvenmediğini gösterir. Bu durumda sorgu optimizörü (Query Optimizer) kısıttan yararlanarak *Foreign Key Join Elimination* yapamaz; sorgu planları kalıcı olarak yavaşlar. Bu durum genellikle geçmişte WITH NOCHECK kullanılarak kısıt açıldığı için oluşur.

2. Yetim (Orphan) Satırları Tespit Edin

sql
SELECT c.* FROM dbo.Siparis c LEFT JOIN dbo.Musteri p ON p.Id = c.MusteriId WHERE c.MusteriId IS NOT NULL AND p.Id IS NULL;

Sorgu boş dönüyorsa sorun veride değil yürütme sırasındadır: Uygulama ebeveyn kaydı commit etmeden çocuk kaydı yazmaya çalışmaktadır.

3. Toplu Yüklemelerde (ETL / Bulk Insert) Doğru Sıralama

ETL süreçlerinde kısıt kapatılacaksa mutlaka WITH CHECK ile geri açılmalıdır:

sql
-- Yükleme öncesi kısıtı geçici devre dışı bırakma: ALTER TABLE dbo.Siparis NOCHECK CONSTRAINT FK_Siparis_Musteri; -- Toplu veri yükleme işlemi yürütülür... -- Yükleme sonrası kısıtı GÜVENİLİR olarak yeniden açma: ALTER TABLE dbo.Siparis WITH CHECK CHECK CONSTRAINT FK_Siparis_Musteri;

WITH CHECK ifadesi mevcut tüm satırları doğrular ve is_not_trusted = 0 değerini garanti eder.

4. Yetim Kayıtları Yönetme

Yetim satırları doğrudan silmek yerine veri sahibiyle mutabık kalınarak bir "Bilinmeyen Müşteri" (Id = 0) kaydına bağlamak veri kaybını önler.


▸Bunu Bir Daha Yaşamamak İçin

Sistem genelinde güvenilmez (is_not_trusted = 1) kısıtları periyodik olarak tarayın:

sql
SELECT OBJECT_NAME(parent_object_id) AS tablo, name AS kisit FROM sys.foreign_keys WHERE is_not_trusted = 1 OR is_disabled = 1;

Bu liste tamamen boş olmalıdır.

Diğer Veritabanı Hata Teşhisleri

Kriz anında başvurabileceğiniz diğer doğrulanmış hata rehberleri.

Tüm Hatalar (50)