SQLite bildiğimiz gibi Foreign Key desteği yok buda bize veri bütünlüğünü sağlamada zorluklar yaşatmaktadır.
Fakat bunuda yapayda olsa sağlamak mümkün.
Trigger lar yardımıyla SQLite
veritabanımıza Foreign Key desteği sağlatabiliriz. Örnek olarak 2 tablo
oluşturuyoruz. Basit olarak 2 tablo birinde blog entry lerini tutacağız
diğerindede kategorileri. Entry ve Category tablomuz arasında ir ilişki var
fakat bunu SQLite tanımlayamıyoruz.
İlk olarak Entry tablosuna yeni bir kayıt eklendiğinde eklenilmeye çalışılan kategorinin Category tablosunda olup olmadığını kontrol edelim. Olmayan bir kategoriye ait entry eklemek istemeyiz heralde :) .
Yapmamız gereken tek şey sözle ifade ettiğimiz bu koşulu SQLite a bir
INSERT
TRIGGER ile belirtmek.
CREATE TRIGGER EntryInsertTrigger
BEFORE INSERT ON Entry
BEGIN
SELECT CASE
WHEN(SELECT CategoryID FROM
Category WHERE CategoryID=NEW.CategoryID)
IS NULL
THEN
RAISE(ABORT,'Eklemeye çalıştığınız kategori
mevcut değil')
END;
END;
Trigger ile Entry tablosuna bir kayıt eklenmeden hemen önce eklenmeye çalışılan CategoryID bir alt sorgu yardımıyla Category tablosunda olup olmadığı kontrol ediliyor.
Eğer yoksa NULL döndürülüyor ve bir hata fırlatılıyor. Böylece Entry tablomuza olmayan bir kategoriye ait entry girişi yapılmasını engelledik. Ya UPDATE işlemi:
CREATE TRIGGER EntryUpdateTrigger
BEFORE UPDATE OF CategoryID ON Entry
BEGIN
SELECT CASE
WHEN(SELECT CategoryID FROM
Category WHERE CategoryID=NEW.CategoryID)
IS NULL
THEN
RAISE(ABORT,'Eklemeye çalıştığınız kategori
mevcut değil')
END;
END;
Evet sadece CategoryID güncellenmeye çalışıldığında devreye girecek bir trigger tanımlayıp INSERT trigger ında yaptığımız işlemi aynen tekrarlıyoruz.
Son olarak bütünlüğü sağlamamız için bir şeye daha ihtiyacımız var. Entry tablosunda bir kaydın silinmesi Category tablosu üzerinde hiçbir etki göstermeyecektir ki zaten böyle birşey de istemiyoruz.
Fakat ya Category tablosunda bir kayıt silinmeye çalışılırsa ne olacak. İşte eğer veri bütünlüğünü sağlamamışsak artık olmayan bir kategoriye ait entry lerimiz olacaktır.
O zaman şöyle birşey yapsak. Category tablosundan bir kayıt silinirken o kategorinin Entry tablosunda kullanılıp kullanmadığına baksak zaten eğer kullanılmamışsa silip silmememiz bir anlam ifade etmeyecektir fakat mevcut bir kayıt varsa sorun çıkacaktır.
Tam bu noktada devreye girip bizde sorunu çözeriz.
CREATE TRIGGER CategoryDeleteTrigger
BEFORE DELETE ON Category
BEGIN
SELECT CASE
WHEN(SELECT COUNT(CategoryID) FROM
Entry WHERE CategoryID=OLD.CategoryID)
> 0
THEN
RAISE(ABORT,'Silmeye çalıştığınız kategori
Entry tablosunda mevcut.')
END;
END;
ve işte bu kadar küçük, şirin, sevimli ve bi o kadarda hızlı veritabanımıza trigger tabanlı foreign key desteği sağladık.Hiçde zor değilmiş değil mi ? :D