Nasıl Kullanılır?
CREATE TABLE tablo_adi ( sutun_adi veritipi, ... ... CONSTRAINT FK_adi FOREIGN KEY (sutun_adi) REFERENCES diger_tablo_adi (diger_tablodaki_ilgili_sutun_adi) ON UPDATE <YAPILACAK_EYLEM> ON DELETE <YAPILACAK_EYLEM> );
Foreign key kısıtlamasına eklenen ON UPDATE ve ON DELETEözellikleri isteğe bağlıdır. ON UPDATE ve ON DELETE özelliği diger_tablo_adi içerisindeki diger_tablodaki_ilgili_sutun_adi ile belirtilen sütunda bir değişiklik olduğunda
Foreign key eylemleri
Foreign key kısıtlamasına ait eylemler kullanılan veritabanlarına göre farklılık göstermektedir.CASCADE: REFERENCES ile belirtilen sütunda bir eylem (UPDATE, DELETE) olduğunda Foreign key ile belirtilen ilişkili sütunda benzer eylemi yapar.
NO ACTION: Foreign key sütunu ve REFERENCES ile belirtilen sütunda bir ilişki varsa, REFERENCES ile belirtilen sütunda bir eyleme (UPDATE, DELETE) izin vermez.
SET NULL: REFERENCES ile belirtilen sütunda bir eylem (UPDATE, DELETE) olduğunda Foreign key ile belirtilen ilişkili sütunu NULL yapar.
NOT: Foreign key sütununda NOT NULL kısıtlaması varsa hata verir.
SET DEFAULT: REFERENCES ile belirtilen sütunda bir eylem (UPDATE, DELETE) olduğunda Foreign key ile belirtilen ilişkili sütuna DEFAULT değerini verir.
NOT: Foreign key sütununda DEFAULT kısıtlaması yoksa hata verir.
RESTIRCT: MySQL VTYS içerisinde bulunan bu eylem NO ACTION ile aynı işleve sahiptir.
Örneğimizi "Şehirler" ve "İlçeler" olmak üzere iki tablo üzerinde yapmaya çalışalım. Şehirler adlı veritabanı tablosunu oluşturalım.
Şehirler Tablosu
CREATE TABLE Sehirler ( sehir_ID INT PRIMARY KEY NOT NULL IDENTITY(1,1), sehir_adi VARCHAR(100) )
Şehirler tablosu oluştu. Birkaç kayıt ekleyelim.
Şehirler Tablosu Verileri
INSERT INTO Sehirler (sehir_adi) VALUES ('Adana'), ('Ankara'), ('İstanbul'), ('Kayseri'), ('Muğla')
Sırada ilçeleri oluşturalım.
İlçeler Tablosu
CREATE TABLE Ilceler ( ilce_ID INT PRIMARY KEY NOT NULL IDENTITY(1,1), sehir_ID INT, ilce_adi VARCHAR(100) )
İlçeler tablosu oluştu. Birkaç kayıt ekleyelim.
İlçeler Tablosu Verileri
INSERT INTO Ilceler (sehir_ID, ilce_adi) VALUES (1, 'Çukurova'), (1, 'Seyhan'), (2, 'Çankaya'), (2, 'Keçiören'), (2, 'Yenimahalle'), (3, 'Yenibosna'), (3, 'Şişli'), (4, 'Kocasinan'), (5, 'Bodrum')
Tablolar ve içerisindeki verileri hazırladık. Şimdi tabloları görüntüleyelim.
Şehirler ve İlçeler Tablosu
Tablolardaki veri bütünlüğünü daha da görebilmek için iki tabloyu JOIN işlemi ile birleştirip ilçenin hangi şehirde olduğunu gösterelim.
Şehirler ve İlçeler JOIN
SELECT A.sehir_ID, A.sehir_adi, B.ilce_ID, B.ilce_adi FROM Sehirler A INNER JOIN Ilceler B ON A.sehir_ID = B.sehir_ID
Şehirler ve İlçeler JOIN
CASCADE FOREIGN KEY
İlçeler tablosuna Şehirler tablosu ile ilişkili FOREIGN KEY (CASCADE işlevine sahip şekilde) belirleyelim.Şehirler ve İlçeler Cascade Foreign Key
ALTER TABLE Ilceler ADD CONSTRAINT FK_Ilceler_sehir_ID FOREIGN KEY (sehir_ID) REFERENCES Sehirler (sehir_ID) ON UPDATE CASCADE ON DELETE CASCADE
Tablolar arası ilişkiyi CASCADE olarak tanımladık. Sehirler tablosundan bir tane şehir silelim.
ID Değeri 2 Olan Şehri Silelim.
DELETE FROM Sehirler WHERE sehir_ID = 2
Şehirler tablosundan silme işlemi gerçekleşti. Ayrıca Ilceler adlı tablodan da sehir_ID=2 olan ilçeler de silinmiş oldu. Aslında bir nevi Trigger (Tetikleyici) işlevi görmüş oluyor.
İlçeler Tablosu
NO ACTION FOREIGN KEY
İlçeler tablosuna Şehirler tablosu ile ilişkili FOREIGN KEY (NO ACTION işlevine sahip şekilde) belirleyelim. Önceki FOREIGN KEY değerini drop edip ardından yeni FOREIGN KEY ekleyelim.Şehirler ve İlçeler No Action Foreign Key
ALTER TABLE Ilceler DROP CONSTRAINT FK_Ilceler_sehir_ID; ALTER TABLE Ilceler ADD CONSTRAINT FK_Ilceler_sehir_ID FOREIGN KEY (sehir_ID) REFERENCES Sehirler (sehir_ID) ON UPDATE No Action ON DELETE No Action
Tablolar arası ilişkiyi ekledik. Şehirler tablosundan bir şehir silelim.
ID Değeri 3 Olan Şehri Silelim.
DELETE FROM Sehirler WHERE sehir_ID = 3
Silmeye çalıştığımız sehir_ID=3 değerli şehre ait ilçe olduğu için bize şu şekilde uyarı verdi.
The DELETE statement conflicted with the REFERENCE constraint "FK_Ilceler_sehir_ID". The conflict occurred in database "denemeDB", table "dbo.Ilceler", column 'sehir_ID'.
Bu şekilde bize tablolar arası ilişki durumuna göre bize uyarı verip veri bütünlüğünü bozmamızı engellemektedir.
SET NULL FOREIGN KEY
İlçeler tablosuna Şehirler tablosu ile ilişkili FOREIGN KEY (SET NULL işlevine sahip şekilde) belirleyelim. Önceki FOREIGN KEY değerini drop edip ardından yeni FOREIGN KEY ekleyelim.Şehirler ve İlçeler SET NULL Foreign Key
ALTER TABLE Ilceler DROP CONSTRAINT FK_Ilceler_sehir_ID; ALTER TABLE Ilceler ADD CONSTRAINT FK_Ilceler_sehir_ID FOREIGN KEY (sehir_ID) REFERENCES Sehirler (sehir_ID) ON UPDATE SET NULL ON DELETE SET NULL
Tablolar arası ilişkiyi ekledik. Şehirler tablosundan bir şehir silelim.
ID Değeri 3 Olan Şehri Silelim.
DELETE FROM Sehirler WHERE sehir_ID = 3
Şehirler tablosundan silme işlemi gerçekleşti. Ayrıca Ilceler adlı tablodan da sehir_ID=3 olan ilçelerin sehir_ID sütunu null olarak güncellenmiş oldu.
Şehirler ve İlçeler Tablosu
SET DEFAULT FOREIGN KEY
İlçeler tablosuna Şehirler tablosu ile ilişkili FOREIGN KEY (SET DEFAULT işlevine sahip şekilde) belirleyelim. Önceki FOREIGN KEY değerini drop edip ardından yeni FOREIGN KEY ekleyelim.Şehirler ve İlçeler SET NULL Foreign Key
ALTER TABLE Ilceler DROP CONSTRAINT FK_Ilceler_sehir_ID; ALTER TABLE Ilceler ADD CONSTRAINT FK_Ilceler_sehir_ID FOREIGN KEY (sehir_ID) REFERENCES Sehirler (sehir_ID) ON UPDATE SET DEFAULT ON DELETE SET DEFAULT
Tablolar arası ilişkiyi ekledik. Şehirler tablosundan bir şehir silelim.
ID Değeri 4 Olan Şehri Silelim.
DELETE FROM Sehirler WHERE sehir_ID = 4
Şehirler tablosundan silme işlemi gerçekleşti. Ayrıca Ilceler adlı tablodan da sehir_ID=4 olan ilçelerin sehir_ID sütunu null olarak güncellenmiş oldu.
Şehirler ve İlçeler Tablosu
RESTIRCT FOREIGN KEY (MYSQL Veritabanı Üzerinde)
İlçeler tablosuna Şehirler tablosu ile ilişkili FOREIGN KEY (RESTIRCT işlevine sahip şekilde) belirleyelim. MySQL veritabanını sıfırdan oluşturduğumuz için henüz bir ilişki kurulmadı o nedenle önceki ilişkiyi drop etmeye gerek kalmamaktadır. RESTIRCT ilişki tipi kurunca anahtar sözcük olarak "RESTIRCT" yazmaya gerek duyulmamaktadır.Şehirler ve İlçeler RESTIRCT Foreign Key
ALTER TABLE Ilceler ADD CONSTRAINT FK_Ilceler_sehir_ID FOREIGN KEY(sehir_ID) REFERENCES Sehirler(sehir_ID)
Tablolar arası ilişkiyi ekledik. Şehirler tablosundan bir şehir silelim.
ID Değeri 1 Olan Şehri Silelim.
DELETE FROM Sehirler WHERE sehir_ID = 1
Silmeye çalıştığımız sehir_ID=1 değerli şehre ait ilçe olduğu için bize şu şekilde uyarı verdi.
[Err] 1451 - Cannot delete or update a parent row: a foreign key constraint fails (`denemedb`.`ilceler`, CONSTRAINT `FK_Ilceler_sehir_ID` FOREIGN KEY (`sehir_ID`) REFERENCES `sehirler` (`sehir_ID`))
Benzer şekilde bize tablolar arası ilişki durumuna göre bize uyarı verip veri bütünlüğünü bozmamızı engelledi.