26 Haziran 2009 Cuma

Parent-Child Tablo ilişkisi ve Cascade Deletion (Kademeli silme) işlemi

Üzerlerinde parent-child ilişkisi tanımlanmış olan tablolar sayesinde tablolardaki verinin bütünlüğünü korumak daha kolay olabilir, örneğin motorlu taşıtların fiyatlarının tutulduğu bir parent tablo üzerinden motorsikletlerin marka ve modellerinin tutulduğu bir child tabloya parent-child ilişkisi tanımlanabilir. Bu şekilde seçilen marka ve modeldeki motorsikletin fiyatına parent tablo üzerinden ulaşılabilir. Bu yapıda Parent-Child ilişkisi kaldırılmadan parent kayıt silinemeyeceğinden her motorsiklet için mutlaka fiyat kaydının olması garanti altına alınmış olacaktır. Böyle bir yapı kurulmuş ise ve eğer veri silinmek isteniyorsa öncelikle child kayıtlar silinmeli ve daha sonra o kayıtlara ait olan parent kayıtlar silinmelidir. Aksi taktirde parentten silme işlemi yapıldığı zaman foreign key constraint hatası alınacaktır.
Ekleme işleminde ise öncelikle parent tabloda fk ilişkisi tanımlanmış alanın verisi girilmiş olmalıdır, daha sonra bu alanla ilişkili child kayıtlar eklenebilecektir. Bu yapı veri ekleme ve silme işlemlerini kısıtlar gibi görünse de tablo üzerindeki veri bütünlüğünü korumaktadır. Ayrıca üzerinde parent-child ilişkisi tablolarda parent tablodaki verinin silinmesi ile onunla ilişkili child kayıtların silinmesini sağlayacak olan bir 'cascade deletion' yapısı mevcuttur. Cascade deletion, seviyeli silme işlemi, parent-child ilişkisinin oluşturulduğu foreign key üzerine tanımlanır.
Aşağıdaki örneklerde parent-child ilişkisinin nasıl kurulacağı, cascade deletion tanımlarının nasıl yapılacağı, üzerine önceden foreign key tanımlamaları yapılmış olan tablolarda cascade deletion işlemi için yapılacak olan değişiklikler basitçe gösterilmiştir.

Öncelikle örnek bir bayi tablosu oluşturalım. Bayi tablosu üzerinde bayi_id ve bayi_adi alanlarını primary key olarak belirleyelim.


CREATE TABLE bayi
( bayi_id numeric(10) not null,
bayi_adi varchar2(50) not null,
iletisim_adi varchar2(50),
CONSTRAINT bayi_pk PRIMARY KEY (bayi_id, bayi_adi)
);


Daha sonra urunler tablosunu oluşturalım ve bu tablo üzerinde bayi tablosuna foreign key olacak alanları belirleyelim.


CREATE TABLE urunler
( urun_id numeric(10) not null,
bayi_id numeric(10) not null,
bayi_adi varchar2(50) not null,
CONSTRAINT fk_bayi
FOREIGN KEY (bayi_id, bayi_adi)
REFERENCES bayi(bayi_id, bayi_adi)
);

Şu anda urunler tablosu ile bayi tablosu arasında bayi_id ve bayi_adi alanlarına göre ilişki kurmuş durumdayız. Artık bayi tablosunun ürünler tablosunun parent tablosu olduğunu ve aynı zamanda urunler tablosunun bayi tablosunun child tablosu olduğunu görebiliriz.
Oluşturmuş olduğumuz tablolara veri ekleyelim:

Öncelikle parent tablo olan bayi tablosuna ekleme yapıyoruz.

INSERT INTO BAYI (
BAYI_ID, BAYI_ADI, ILETISIM_ADI)
VALUES ( 1,'bayi1','bayi1_iletişim_adresi');
INSERT INTO BAYI (
BAYI_ID, BAYI_ADI, ILETISIM_ADI)
VALUES ( 2,'bayi2','bayi2_iletişim_adresi');
INSERT INTO BAYI (
BAYI_ID, BAYI_ADI, ILETISIM_ADI)
VALUES ( 3,'bayi3','bayi3_iletişim_adresi');
INSERT INTO BAYI (
BAYI_ID, BAYI_ADI, ILETISIM_ADI)
VALUES ( 4,'bayi4','bayi4_iletişim_adresi');
COMMIT;

--1 row created.
--1 row created.
--1 row created.
--1 row created.
--Commit complete.

Daha sonra child tablo olan urunler tablosuna ekleme yapıyoruz.

INSERT INTO URUNLER (
URUN_ID, BAYI_ID, BAYI_ADI)
VALUES ( 01,1,'bayi1');
INSERT INTO URUNLER (
URUN_ID, BAYI_ID, BAYI_ADI)
VALUES ( 02,2,'bayi2');
INSERT INTO URUNLER (
URUN_ID, BAYI_ID, BAYI_ADI)
VALUES ( 03,3,'bayi3');
INSERT INTO URUNLER (
URUN_ID, BAYI_ID, BAYI_ADI)
VALUES ( 04,4,'bayi4');
COMMIT;

--1 row created.
--1 row created.
--1 row created.
--1 row created.
--Commit complete.

Kontrollü bir şekilde önce parent sonra ise chil tabloya ekleme yaptığımız için herhangi bir hata ile karşılaşmadık.

Fakat urunler tablosuna bayi_id'si 5 ve bayi_adi bayi5 olan bir kaydı eklemeye çalıştığımızda ORA-02291 kodlu hata ile karşılaşırız. Çünkü parent tabloda bulunmayan bir kayıdı onun child tablosuna insert etmeye çalışıyoruz.

ORA-02291: integrity constraint (CCSOWNER.FK_BAYI) violated - parent key not found

Tam tersi olacak şekilde parent tablo olan URUNLER tablosundaki URUN_ID = 1 olan kayıdı silmeye çalıştığımızda da aşağıdaki gibi bir hata ile karşılaşırız. Parent tablodan silme yaparken child tablodan da silmemiz grektiği için veri bütünlüğü korunmuş olur.

ORA-02292: integrity constraint (MDSTAGE.FK_BAYI) violated - child record found

Bahsedildiği şekilde veri bütünlüğünü korumak bazı çalışmalarda büyük ölçüde istediğimiz bir özelliktir fakat silme yaparken daha büyük bir yapıda hangi tablonun hangisinin parenti olduğu gibi sorunlarla uğraşmak istemeyiz, bunun için parent-child ilişkisindeki yapılarda cascade delete (kademeli silme) özelliğini kullanabiliriz.
Kademeli silme özelliği ile bir parent tablodan veri silindiğinde otomatik olarak tüm bağlı child tablolardaki veri de silinir, ver bu şekilde veri bütünlüğü korunur.

Cascade deletion yapısı için ilişkiyi kurduğumuz ikincil anahtar (foreign key) üzerinde ON DELETE CASCADE tanımı yaparız. URUNLER tablosunu aşağıdaki gibi yeniden düzenleyecek olursak, cascade deletion yapan bir yapıyı elde etmiş oluruz.

CREATE TABLE urunler
( urun_id numeric(10) not null,
bayi_id numeric(10) not null,
bayi_adi varchar2(50) not null,
CONSTRAINT fk_bayi
FOREIGN KEY (bayi_id, bayi_adi)
REFERENCES bayi(bayi_id, bayi_adi)
ON DELETE CASCADE
);

veya bir tablo üzerinde önceden oluşturulmuş olan anahtar alanlarda alter table işlemi ile cascade deletion yapısı oluşturabiliriz.

ALTER TABLE urunler
add CONSTRAINT fk_bayi
FOREIGN KEY (bayi_id )
REFERENCES supplier(bayi_id)
ON DELETE CASCADE;

Hiç yorum yok:

Yorum Gönder

Popüler Yayınlar