SQL tabanlı veritabanlarında veri bütünlüğünü ve tutarlılığını sağlamanın iki temel taşı, veritabanı ilişkileri ve normalizasyondur. Bu kavramlar, verilerin nasıl depolandığını, birbirleriyle nasıl bağlantı kurduğunu ve gereksiz tekrarların nasıl önlendiğini belirler. Etkili bir veritabanı tasarımı, performansı optimize ederken veri anormalliklerini minimize eder, bu da daha güvenilir ve yönetilebilir sistemler oluşturmanın anahtarıdır. Bu makale, her iki konuyu derinlemesine inceleyecektir.
Veritabanı İlişkilerine Derinlemesine Bakış
Veritabanı ilişkileri, bir ilişkisel veritabanındaki tabloların birbirleriyle nasıl etkileşim kurduğunu tanımlar. Bu ilişkiler, veriler arasındaki mantıksal bağlantıları kurar ve veri bütünlüğünü korumak için hayati öneme sahiptir. Temelde, bir tablonun birincil anahtarı (Primary Key – PK) ile başka bir tablonun yabancı anahtarı (Foreign Key – FK) arasındaki bağlantılar aracılığıyla kurulurlar. Yabancı anahtar, diğer tablodaki birincil anahtara referans vererek iki tablo arasında bir köprü görevi görür.
Bire Bir (One-to-One) İlişki
Bire bir ilişki, bir tablodaki her bir kaydın, ilişkili olduğu diğer tablodaki yalnızca bir kayıtla eşleştiği durumu ifade eder. Bu tür ilişkiler genellikle iki ana nedenden kullanılır: ya çok fazla sütunu olan bir tabloyu bölerek yönetilebilirliği artırmak için ya da hassas verileri ayrı bir tabloda tutarak güvenliği artırmak için. Örneğin, bir Kullanicilar tablosundaki her kullanıcının yalnızca bir KullaniciDetaylari kaydı olabilir. Bu durumda, KullaniciDetaylari tablosunda, Kullanicilar tablosundaki KullaniciID‘yi referans gösteren bir yabancı anahtar bulunur ve bu yabancı anahtara bir benzersiz (UNIQUE) kısıtlaması eklenerek bire bir ilişki sağlanır.
CREATE TABLE Kullanicilar (
KullaniciID INT PRIMARY KEY,
KullaniciAdi VARCHAR(50) UNIQUE,
Eposta VARCHAR(100)
);
CREATE TABLE KullaniciDetaylari (
DetayID INT PRIMARY KEY,
KullaniciID INT UNIQUE, -- Bire Bir ilişki için UNIQUE kısıtlaması
Adres VARCHAR(255),
Telefon VARCHAR(20),
FOREIGN KEY (KullaniciID) REFERENCES Kullanicilar(KullaniciID)
);
Bire Çok (One-to-Many) İlişki
Bire çok ilişki, en yaygın veritabanı ilişkisi türüdür. Bu ilişkide, bir tablodaki tek bir kayıt, başka bir tablodaki birden fazla kayıtla ilişkilendirilebilir, ancak diğer tablodaki her bir kayıt, ilk tablodaki yalnızca bir kayıtla ilişkilendirilir. Örneğin, bir Musteriler tablosundaki bir müşteri, Siparisler tablosunda birden fazla siparişe sahip olabilir, ancak her sipariş yalnızca bir müşteriye aittir. Bu ilişki, Siparisler tablosunda Musteriler tablosunun birincil anahtarını (MusteriID) referans gösteren bir yabancı anahtar (MusteriID) tanımlanarak kurulur.
CREATE TABLE Musteriler (
MusteriID INT PRIMARY KEY,
Ad VARCHAR(50),
Soyad VARCHAR(50)
);
CREATE TABLE Siparisler (
SiparisID INT PRIMARY KEY,
MusteriID INT, -- Yabancı anahtar
SiparisTarihi DATE,
ToplamTutar DECIMAL(10, 2),
FOREIGN KEY (MusteriID) REFERENCES Musteriler(MusteriID)
);
Çoka Çok (Many-to-Many) İlişki
Çoka çok ilişki, bir tablodaki birden fazla kaydın, başka bir tablodaki birden fazla kayıtla ilişkilendirilebildiği durumu ifade eder. Bu tür ilişkiler doğrudan iki tablo arasında kurulamaz; bunun yerine, genellikle “ilişki tablosu” veya “birleştirici tablo” (junction table) adı verilen üçüncü bir aracı tablo kullanılarak çözülür. Örneğin, bir öğrenci birden fazla ders alabilir ve bir ders birden fazla öğrenciye sahip olabilir. Bu durumu yönetmek için Ogrenciler, Dersler ve OgrenciDersleri adında bir tabloya ihtiyaç duyulur. OgrenciDersleri tablosu, Ogrenciler tablosundan OgrenciID‘yi ve Dersler tablosundan DersID‘yi yabancı anahtar olarak içerir ve genellikle bu iki anahtarın birleşimi birincil anahtarı oluşturur.
CREATE TABLE Ogrenciler (
OgrenciID INT PRIMARY KEY,
Ad VARCHAR(50),
Soyad VARCHAR(50)
);
CREATE TABLE Dersler (
DersID INT PRIMARY KEY,
DersAdi VARCHAR(100),
Kredi INT
);
CREATE TABLE OgrenciDersleri (
OgrenciID INT,
DersID INT,
PRIMARY KEY (OgrenciID, DersID), -- Bileşik birincil anahtar
FOREIGN KEY (OgrenciID) REFERENCES Ogrenciler(OgrenciID),
FOREIGN KEY (DersID) REFERENCES Dersler(DersID)
);
Veritabanı Normalizasyonu: Temeller ve Formlar
Normalizasyon, bir veritabanı tasarımını, veri yedekliliğini (redundancy) azaltmak ve veri anormalliklerini (anomalies) önlemek amacıyla belirli kurallar veya “normal formlar” çerçevesinde düzenleme sürecidir. Temel amacı, veri bütünlüğünü sağlamak, veritabanı boyutunu optimize etmek ve ekleme, güncelleme ve silme işlemlerinde ortaya çıkabilecek tutarsızlıkları minimize etmektir. Normalizasyon, bir tablonun hangi formda olduğunu belirlemek için fonksiyonel bağımlılıkları inceler.
- Ekleme Anormalliği (Insertion Anomaly): Yeni bir veri eklerken, ilgisiz veya eksik veri eklemek zorunda kalma.
- Silme Anormalliği (Deletion Anomaly): Bir veriyi silerken, başka değerli bir verinin de yanlışlıkla silinmesi.
- Güncelleme Anormalliği (Update Anomaly): Bir veriyi güncellerken, aynı verinin birden fazla yerde tutulması nedeniyle tüm kopyalarını güncellemeyi unutma ve tutarsızlık yaşanması.
Birinci Normal Form (1NF)
Bir tablonun 1NF’de olabilmesi için şu koşulları sağlaması gerekir:
- Her hücrede atomik (bölünemez) değerler bulunmalıdır. Yani, bir hücrede birden fazla değer veya virgülle ayrılmış değerler olmamalıdır.
- Her bir sütunun tek bir veri türü olmalı ve tekrarlayan gruplar içermemelidir.
- Her bir satır benzersiz olmalıdır (bir birincil anahtar ile tanımlanabilir).
Örnek olarak, bir Calisanlar tablosunda TelefonNumaralari sütunu, bir çalışanın birden fazla telefon numarasına sahip olabileceği ve bunları virgülle ayırarak tuttuğu bir yapı 1NF’ye aykırıdır. Bu durumda, her telefon numarası için ayrı bir satır oluşturulmalı veya telefon numaraları için ayrı bir tablo oluşturulmalıdır.
İkinci Normal Form (2NF)
Bir tablonun 2NF’de olabilmesi için şu koşulları sağlaması gerekir:
- 1NF’de olmalıdır.
- Anahtar olmayan (non-key) her öznitelik, birincil anahtarın tamamına fonksiyonel olarak bağlı olmalıdır. Yani, birincil anahtar bileşikse (birden fazla sütundan oluşuyorsa), anahtar olmayan hiçbir öznitelik birincil anahtarın yalnızca bir kısmına bağlı olmamalıdır. Bu durum “kısmi bağımlılık” olarak bilinir.
Örnek: Bir SiparisDetaylari tablosu (SiparisID, UrunID, Miktar, UrunAdi, UrunFiyati) birincil anahtarı (SiparisID, UrunID) olsun. Burada UrunAdi ve UrunFiyati sadece UrunID‘ye bağlıdır, SiparisID‘ye değil. Bu, kısmi bağımlılıktır. 2NF için UrunAdi ve UrunFiyati bilgilerini ayrı bir Urunler tablosuna taşımak gerekir.
Üçüncü Normal Form (3NF)
Bir tablonun 3NF’de olabilmesi için şu koşulları sağlaması gerekir:
- 2NF’de olmalıdır.
- Anahtar olmayan hiçbir öznitelik, birincil anahtarın başka bir anahtar olmayan özniteliğine geçişli (transitive) olarak bağlı olmamalıdır. Yani, A -> B ve B -> C bağımlılıkları varsa (burada A birincil anahtardır ve B anahtar olmayan bir özniteliktir), C özniteliği B’ye geçişli olarak bağlıdır.
Örnek: Bir Personel tablosu (PersonelID, Ad, Soyad, DepartmanAdi, DepartmanTelefonu) olsun ve PersonelID birincil anahtar olsun. Burada DepartmanTelefonu, DepartmanAdi‘na bağlıdır ve DepartmanAdi da PersonelID‘ye bağlıdır. Yani PersonelID -> DepartmanAdi -> DepartmanTelefonu bir geçişli bağımlılıktır. 3NF için DepartmanAdi ve DepartmanTelefonu bilgilerini ayrı bir Departmanlar tablosuna taşımak gerekir.
BCNF (Boyce-Codd Normal Form)
BCNF, 3NF’nin daha katı bir versiyonudur. Bir tablo BCNF’de olmak için 3NF’de olmalı ve ek olarak, her determinat (belirleyici), bir aday anahtar olmalıdır. Yani, bir öznitelik veya öznitelik kümesi başka bir öznitelik veya öznitelik kümesini belirliyorsa, bu belirleyici bir aday anahtar olmak zorundadır. Nadir durumlarda 3NF’de olan ancak BCNF’de olmayan tablolar ortaya çıkabilir, genellikle birden fazla çakışan aday anahtarın bulunduğu durumlar için geçerlidir.
İlişkiler ve Normalizasyonun SQL Uygulamaları
SQL, veritabanı ilişkilerini ve normalizasyon prensiplerini uygulamak için çeşitli mekanizmalar sunar. PRIMARY KEY, FOREIGN KEY ve UNIQUE kısıtlamaları bu yapının temelini oluşturur. PRIMARY KEY, bir tablodaki her satırı benzersiz şekilde tanımlarken, FOREIGN KEY bir tablonun başka bir tablodaki birincil anahtara referans vermesini sağlar ve bu sayede referans bütünlüğünü (referential integrity) korur. UNIQUE kısıtlaması ise, belirli bir sütundaki tüm değerlerin benzersiz olmasını garanti eder ve bire bir ilişkilerin kurulmasında rol oynayabilir.
Bu kısıtlamalar sayesinde, SQL veritabanı motoru, tanımlanan ilişkisel kurallara uymayan herhangi bir veri değişikliğini (ekleme, güncelleme, silme) otomatik olarak reddeder. Örneğin, bir Musteriler tablosunda olmayan bir MusteriID ile Siparisler tablosuna kayıt eklemeye çalışmak, bir yabancı anahtar kısıtlaması ihlaline yol açar ve işlem başarısız olur. Bu, veri tutarlılığının sağlanmasında kritik bir rol oynar.
Referans bütünlüğü kısıtlamaları, SQL’de ON DELETE ve ON UPDATE kuralları ile daha da esneklik kazanır:
CASCADE: Ana tablodaki kayıt silindiğinde/güncellendiğinde, ilişkili tablodaki tüm ilgili kayıtları da siler/günceller.SET NULL: Ana tablodaki kayıt silindiğinde/güncellendiğinde, ilişkili tablodaki yabancı anahtar sütununu NULL yapar (eğer NULL değerine izin veriyorsa).RESTRICT(varsayılan): İlişkili tablolarda ilgili kayıtlar varken ana tablodaki kaydın silinmesini/güncellenmesini engeller.NO ACTION: RESTRICT’e benzer, ancak standartlar arasında küçük farkları olabilir.
-- Normalizasyon ve ilişkileri gösteren örnek tablo yapıları
CREATE TABLE Departmanlar (
DepartmanID INT PRIMARY KEY,
DepartmanAdi VARCHAR(100) UNIQUE,
Lokasyon VARCHAR(100)
);
CREATE TABLE Calisanlar (
CalisanID INT PRIMARY KEY,
Ad VARCHAR(50),
Soyad VARCHAR(50),
DepartmanID INT, -- Yabancı anahtar
Maas DECIMAL(10, 2),
FOREIGN KEY (DepartmanID) REFERENCES Departmanlar(DepartmanID)
ON DELETE RESTRICT ON UPDATE CASCADE -- İlişkisel eylemler
);
CREATE TABLE Projeler (
ProjeID INT PRIMARY KEY,
ProjeAdi VARCHAR(100),
Butce DECIMAL(15, 2)
);
CREATE TABLE CalisanProjeleri (
CalisanID INT,
ProjeID INT,
AtanmaTarihi DATE,
PRIMARY KEY (CalisanID, ProjeID),
FOREIGN KEY (CalisanID) REFERENCES Calisanlar(CalisanID) ON DELETE CASCADE,
FOREIGN KEY (ProjeID) REFERENCES Projeler(ProjeID) ON DELETE CASCADE
);
Veritabanı ilişkileri ve normalizasyon, modern SQL veritabanı tasarımının temel taşlarıdır. Doğru ilişkileri kurmak ve veritabanını uygun normal formlara getirmek, veri bütünlüğünü artırır, veri tekrarlarını azaltır ve olası anormallikleri önler. Bu prensipler, daha sağlam, ölçeklenebilir ve yönetilebilir veritabanı sistemleri oluşturarak uygulamanın performansını ve güvenilirliğini doğrudan etkiler. Bu nedenle, her veritabanı geliştiricisinin bu kavramlara hakim olması kritik öneme sahiptir.