Bu yazımda sizlere MySQL de Foreign Key kullanımından bahsedeceğim. Foreign Key kullanırken bilmemiz gereken bazı hususlar var. Kısaca onlardan bahsedeyim. Foreign Key kullanırken iki olayımız mevcut. Bunlar ON DELETE (silme işleminde) ve ON UPDATE (güncelleme işleminde). Ana tabloda kayıt silindiğinde ilişki kontrolü yapılmasını istiyorsak ON DELETE olayını kullanacağız. Ana tabloda kayıt güncellendiğinde ilişki kontrolü yapılmasını istiyorsak ON UPDATE olayını kullanacağız. Bu iki olayı birliktede kullanabliiriz. Bu olayları kullanırken ilişki kontrolümüzün nasıl olacağına karar vereceğimiz bazı parametreler var. Onlar CASCADE, SET NULL, RESTRICT ve NO ACTION parametreleridir. CASCADE kullanırsak ana tabloda kayıt silindiğinde ona bağlı çocuk tabloda ki kayıt da silinecektir. Ana tabloda ki kayıtın ilişkili alanı güncellenirse ona bağlı çocuk tablodaki ilişkili alan da güncellenecektir. CASCADE parametresi ON DELETE ve ON UPDATE olayının ikisinde de kullanılabilmektedir. SET NULL kullanırsak ana tablodaki kayıt silindiğinde çocuk tablodaki ilişkili kayıttaki ilişkili alan NULL değerini alacaktır. Ana tabloda ilişkili kayıttaki ilişkili alan güncellendiğinde ona bağlı olan çocuk tablodaki ilişkili kayıttaki ilişkili alan NULL değerini alacaktır. SET NULL kullanabilmemiz için çocuk tablodaki ilişki kuracağımız alan NULL olabilmesi gerekmektedir. Aksi halde SET NULL olarak ilişki kurmamıza izin verilmemektedir. İki olayda kullanılmaktadır. RESTRICT ve NO ACTION parametreleri arasında fark yoktur. İkiside aynı işi yapmaktadır. Bunları kullanırsak ana tablodan kayıt silmek istediğimizde ona bağlı çocuk tabloda ilişkili kayıt varsa buna izin vermemektedir. Ana tablodan ilişkili kayıtın ilişkili alanı güncellenirse eğer ona bağlı çocuk tabloda bir kayıt varsa buna da izin vermemektedir. Foreign Key kullanabilmemiz için veritabanı motorumuzun INN0DB olması gerekmektedir. MyISAM motoru bunu desteklememektedir. Foreign Key kullabilmemiz için INDEX tanımlamamız gerekmektedir. Bu kadar bilgiden sonra örneklerimize geçebiliriz. Aşağıdaki gibi sample veritabanı altında ana tablo olarak musteri tablosu ve çocuk tablo olarak siparis tablosu olsun.

CREATE TABLE `musteri` (
 `musteri_id` int(11) NOT NULL AUTO_INCREMENT,
 `musteri_adi` varchar(50) NOT NULL,
 `musteri_soyadi` varchar(50) NOT NULL,
 `musteri_email` varchar(50) NOT NULL,
 PRIMARY KEY (`musteri_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

Musteri Tablosu:

CREATE TABLE `siparis` (
 `siparis_id` int(11) NOT NULL AUTO_INCREMENT,
 `musteri_id` int(11) NOT NULL,
 `siparis_kodu` varchar(10) NOT NULL,
 `siparis_adi` varchar(50) NOT NULL,
 PRIMARY KEY (`siparis_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

Siparis Tablosu:

Siparis tablosundaki musteri_id ile Musteri tablosundaki musteri_id yi arasında ilişki kuracağımız için , siparis tablosunda ki musteri_id yi INDEX olarak tanımlamamız gerekmektedir.

Resimdeki kırmızı dikdörtgen içindeki icona tıklayarak INDEX imizi oluşturabiliriz.

ALTER TABLE `siparis` ADD INDEX ( `musteri_id` )

INDEX imizi oluşturduktan sonra yukardaki resimdeki mavi dikdörtgen içerisinde index lerde görünmesi gerekmektedir. Siparis tablosunu musteri tablosuna bağlayacağımız için ilişkiyi siparis tablosu üzerinden kurmamız gerekiyor. Bunun için siparis tablosunda yukardaki resimdeki gibi yeşil dikdörtgen içindeki İlişki görünümü yazan yere tıklıyoruz. Karşımıza aşağıdaki gibi bir ekran gelecektir.

Bu ekranda siparis tablosundaki musteri_id alanını , ikinci açılır listeden sample.musteri.musteri_id seçeneğini seçerek musteri tablosundaki musteri_id ile bağlamış oluyoruz. ON DELETE ve ON UPDATE olaylarında ise örnek olduğu için CASCADE seçtim. Bunlar sizin ilişkinizin türüne göre değişkenlik gösterebilir. Sağ alt köşedeki KAYDET butonuna tıklayarak ilişkimizi oluşturalım.

ALTER TABLE `siparis` ADD FOREIGN KEY ( `musteri_id` ) REFERENCES `sample`.`musteri` (
`musteri_id`
) ON DELETE CASCADE ON UPDATE CASCADE ;

Şimdi ise sizlere gerçekleşen olaylar sonucu ne gibi çıktılar alacağımızı izah edeyim. Örnek olarak musteri tablomuzda aşağıdaki gibi kayıtlar olsun.
Siparis tablomuza aşağıdaki gibi musteri_id si 5 olan kayıt eklemek istediğimizde;

INSERT INTO siparis (musteri_id,siparis_kodu,siparis_adi) VALUES (5,'123456','Bilgisayar');

#1452 – Cannot add or update a child row: a foreign key constraint fails (`sample`.`siparis`, CONSTRAINT `siparis_ibfk_1` FOREIGN KEY (`musteri_id`) REFERENCES `musteri` (`musteri_id`) ON DELETE CASCADE ON UPDATE CASCADE)” uyarısı ile karşılaşacağız. Çünkü ana tablomuz olan musteri tablosunda musteri_id si 5 olan bir kayıt bulunmamaktadır. Bu yüzden eklememize izin verilmemektedir.
ON DELETE olayında:
CASCADE olarak ilişki kurduğumuzda, ana tablo olan musteri tablosunda musteri_id si 1 olan kaydı sildiğimizde ona bağlı olan siparis tablosunda ki kayıtlarda musteri_id si 1 olan bütün kayıtlar silinecektir.
SET NULL olarak ilişki kurduğumuzda, ana tablo olan musteri tablosunda musteri_id si 1 olan kaydı sildiğimizde ona bağlı olan siparis tablosunda ki kayıtlarda musteri_id si 1 olan bütün kayıtların musteri_id si NULL olacaktır. Bu örnekte siparis tablosundaki musteri_id alanı NOT NULL olduğundan SET NULL tipinde ilişki kurmamız mümkün değildir.
RESTRICT veya NO ACTION olarak ilişki kurduğumuzda, ana tablo olan musteri tablosunda musteri_id si 1 olan kaydı silmek istediğimizde ona bağlı olan siparis tablosunda musteri_id si 1 olan bir kayıt varsa bu işleme izin vermemektedir. “#1451 – Cannot delete or update a parent row: a foreign key constraint fails (`sample`.`siparis`, CONSTRAINT `siparis_ibfk_1` FOREIGN KEY (`musteri_id`) REFERENCES `musteri` (`musteri_id`)) ” uyarısı ile karşılacağız.

Bu örnekte ana tablo olan musteri tablosundaki musteri_id alanı AUTO_INCREMENT olduğunda musteri_id alanındaki veri üzerinde güncelleme yapamayız. musteri_id alanının AUTO_INCREMENT olmadığını varsayalım.

ON UPDATE olayında:
CASCADE olarak ilişki kurduğumuzda, ana tablo olan musteri tablosunda musteri_id si 1 olan kaydın musteri_id sini 10 yaptığımızda ona bağlı olan siparis tablosunda ki kayıtlarda musteri_id si 1 olan bütün kayıtların musteri_id si 10 olacaktır.
SET NULL olarak ilişki kurduğumuzda, ana tablo olan musteri tablosunda musteri_id si 1 olan kaydın musteri_id sini 10 yaptığımızda ona bağlı olan siparis tablosunda ki kayıtlarda musteri_id si 1 olan bütün kayıtların musteri_id si NULL olmaktadır. Bu örnekte siparis tablosundaki musteri_id alanı NOT NULL olduğundan SET NULL tipinde ilişki kurmamız mümkün değildir.
RESTRICT veya NO ACTION olarak ilişki kurduğumuzda, ana tablo olan musteri tablosunda musteri_id si 1 olan kaydın musteri_id sini değiştirmek istediğimizde ona bağlı olan siparis tablosunda musteri_id si 1 olan bir kayıt varsa bu işleme izin vermemektedir. “#1451 – Cannot delete or update a parent row: a foreign key constraint fails (`sample`.`siparis`, CONSTRAINT `siparis_ibfk_1` FOREIGN KEY (`musteri_id`) REFERENCES `musteri` (`musteri_id`)) ” uyarısı ile karşılacağız.