Yabancı Anahtar (Foreign Key) Nedir?
Kısa tanım
Yabancı anahtar (foreign key), bir tablodaki sütunun değerinin başka bir tablodaki birincil anahtar veya benzersiz bir sütunda gerçekten var olmasını zorunlu kılan kısıttır. Böylece var olmayan bir müşteriye ait sipariş gibi “yetim” kayıtların oluşması engellenir; buna referans bütünlüğü denir. ON DELETE ve ON UPDATE kurallarıyla, başvurulan satır silindiğinde veya değiştiğinde bağlı satırlara ne olacağı da tanımlanır.
Diğer adları: foreign key, FK, dış anahtar, referans kısıtı

Referans bütünlüğü: yetim kayıt olmasın
Bir orders tablosundaki customer_id sütunu, customers tablosundaki bir satırı gösterir. Yabancı anahtar, bu göstergenin her zaman var olan bir satıra işaret etmesini veritabanı düzeyinde garanti eder. Var olmayan bir müşteri kimliğiyle sipariş eklemeye çalışmak hata verir; siparişleri olan bir müşteriyi silmek de, tanımlanan kurala göre ya engellenir ya da siparişlere bir şey olur.
Aynı kontrolü uygulama kodunda yapmak mümkün görünse de güvenilir değildir. Eşzamanlı iki istek arasında yarış durumu oluşabilir, veritabanına başka bir servis veya elle çalıştırılan bir betik yazabilir, kodda bir kontrol unutulabilir. Kısıt veritabanında olduğunda bu yolların hiçbiri tutarsız veri üretemez.
CREATE TABLE orders (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
customer_id bigint NOT NULL
REFERENCES customers (id) ON DELETE RESTRICT,
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE order_items (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
order_id bigint NOT NULL
REFERENCES orders (id) ON DELETE CASCADE,
sku text NOT NULL,
qty integer NOT NULL CHECK (qty > 0)
);Başvurulan sütun genellikle hedef tablonun birincil anahtarıdır; benzersizliği garanti edilmiş başka bir sütun da olabilir.
ON DELETE seçenekleri
| Kural | Üst satır silinince |
|---|---|
NO ACTION (varsayılan) | Bağlı satır varsa hata verir; PostgreSQL'de kontrol ertelenebilir (deferrable) ve işlemin sonuna bırakılabilir |
RESTRICT | Bağlı satır varsa silmeyi hemen reddeder; ertelenemez |
CASCADE | Bağlı satırları da siler |
SET NULL | Bağlı satırlardaki yabancı anahtar sütununu NULL yapar |
SET DEFAULT | Sütunu varsayılan değerine çeker; MySQL'in InnoDB motoru bu kuralı kabul etmez |
Aynı kurallar ON UPDATE için de tanımlanabilir, ancak birincil anahtarlar değişmeyecek şekilde tasarlandığında bu nadiren gerekir. Ertelenmiş kontrol, birbirine başvuran iki satırı aynı veritabanı işlemi içinde eklemek gibi durumlarda işe yarar.
Hangi ilişkide hangi kural?
- Parçası olduğu bütünle yaşayan kayıtlar: Sipariş satırları siparişsiz bir anlam taşımaz;
CASCADEdoğaldır. - Bağımsız ama tarihsel kayıtlar: Bir müşterinin siparişleri ve faturaları muhasebe açısından saklanmak zorunda olabilir. Burada
RESTRICTseçmek ve müşteriyi silmek yerine pasifleştirmek ya da kişisel verilerini anonimleştirmek daha güvenlidir. - İsteğe bağlı ilişkiler: Bir destek talebine atanmış personel ayrılırsa talep ortadan kalkmamalıdır;
SET NULLuygundur.
CASCADE zincirleri dikkatle izlenmelidir: müşteri → sipariş → sipariş satırı → iade gibi bir zincirde tek bir DELETE, beklenenden çok daha fazla veriyi sessizce silebilir.
Performans ve işletim notları
- İndeks: Üst tablodan bir satır silindiğinde veritabanı alt tabloda bağlı satır arar. PostgreSQL, yabancı anahtar sütununa otomatik indeks eklemez; bu sütunlar çoğu zaman elle indekslenmelidir. MySQL'in InnoDB motoru ise gerekli indeksi kendisi oluşturur.
- Toplu yükleme: Her satırda yapılan kontrol, milyonlarca satırlık yüklemelerde fark edilir bir maliyet getirir.
- Var olan tabloya eklemek: Kısıt eklenirken mevcut tüm satırlar doğrulanır. PostgreSQL'de kısıtı önce
NOT VALIDolarak ekleyip ardındanVALIDATE CONSTRAINTile doğrulamak, büyük tablolarda kilit süresini kısaltır. - Servis sınırları: Yabancı anahtarlar yalnızca aynı veritabanı içinde çalışır. Her servisin kendi veritabanına sahip olduğu bir mikroservis mimarisinde servisler arası tutarlılık uygulama düzeyinde, olaylar ve telafi adımlarıyla sağlanmak zorundadır.

