ER diyagramı, SQL tablolarını oluşturmadan önce uygulamadaki varlıkları, bu varlıkların özelliklerini ve aralarındaki kuralları görünür hâle getirir. Böylece doğrudan tablo açıp sonradan düzeltme yapmak yerine, önce sistemin nasıl çalışacağını kavramsal olarak tasarlarsınız.
Örneğin bir öğrenci-ders-kayıt sistemi geliştiriyorsanız önce “Öğrenci kimdir, ders nedir, kayıt neyi bağlar?” sorularını yanıtlamak gerekir. Sağlam bir veri modelinde karar akışı şu beş aşamadan oluşur: varlıkları çıkar, anahtarları seç, ilişkileri ve cardinality’yi belirle, tabloları üret, tutarlılık kontrolü yap.
ER diyagramı, SQL tablo tasarımından önce neyi çözer?
Bir CRUD projesinde kullanıcı ekleme, listeleme, güncelleme ve silme işlemlerine geçmeden önce verinin yapısını anlamak gerekir. CRUD ekranları genellikle uygulamanın görünen kısmıdır; ancak bu ekranların doğru çalışması, arka plandaki tabloların ve ilişkilerin doğru kurulmasına bağlıdır.
Örneğin bir okul sistemi için doğrudan ogrenciler adlı bir tablo açtığınızı düşünün. Kısa süre sonra bu tabloya ders adı, öğretmen adı, sınıf bilgisi ve kayıt tarihi gibi alanlar eklemeye başlayabilirsiniz. Fakat bir öğrencinin birden fazla derse katılması gerektiğinde aynı öğrenci bilgilerini tekrar tekrar yazmanız gerekir. Bu yaklaşım, hangi bilginin nerede tutulacağı ve kayıtların nasıl bağlanacağı konusunda belirsizlik oluşturur.
ER diyagramı bu belirsizliği SQL yazmadan önce ortaya çıkarır. Diyagram sayesinde şu soruların cevabı görünür olur:
- Sistemde ayrı ayrı takip edilmesi gereken nesneler hangileridir?
- Her nesnenin hangi özellikleri vardır?
- Bir nesne diğerine nasıl bağlanır?
- Bir öğrenci kaç derse kayıt olabilir?
- Bir ders kaç öğrenci içerebilir?
- Aynı öğrencinin aynı derse birden fazla kez kaydolması engellenmeli midir?
Bu sorular yanıtlanmadan yazılan SQL kodu çalışabilir; ancak çalışması doğru tasarlandığı anlamına gelmez. Bir sorgunun hata vermemesi ile veri modelinin uzun vadede tutarlı olması farklı konulardır. ER diyagramı, özellikle ilk CRUD projesinde, kod yazmadan önce düşünülmesi gereken iş kurallarını görünür kılar.
ER diyagramı neden doğrudan tablo açmaktan daha güvenlidir?
Tablo tasarımına hemen başlandığında geliştirici çoğu zaman ekranları takip eder. “Öğrenci ekleme formunda hangi alanlar var?” sorusundan yola çıkarak sütunlar oluşturur. Oysa veri modeli yalnızca formlardan oluşmaz. Bir öğrenci ekranında ders bilgisi görünmeyebilir; fakat öğrencinin hangi derslere kayıt olduğu sistemin temel kurallarından biri olabilir.
ER diyagramı, ekranlardan bağımsız bir veri haritası oluşturur. Bu haritada öğrenci, ders ve kayıt ayrı kavramlar olarak değerlendirilir. Böylece ders bilgileri öğrenci kaydına, öğrenci bilgileri de ders kaydına gereksiz biçimde tekrar yazılmaz. Her bilgi, ait olduğu varlıkla ilişkilendirilir.
Bu yaklaşım özellikle aşağıdaki durumlarda işe yarar:
- Birden fazla ekran aynı veriyi kullanıyorsa
- Bir kaydın başka kayıtlarla bağlantısı varsa
- Verilerin tekrarlanması güncelleme sorununa yol açabilecekse
- Projeye daha sonra yeni özellikler eklenmesi bekleniyorsa
- Birden fazla geliştirici aynı veritabanı üzerinde çalışacaksa
Beş aşamalı karar akışı
Öğrenci-ders-kayıt sistemi gibi bir senaryoyu analiz ederken her ilişkiyi aynı karar akışıyla incelemek, rastgele sütun eklemeyi önler.
- Varlıkları çıkar: Sistemde ayrı izlenmesi gereken nesneleri belirle. Öğrenci, ders ve kayıt bu senaryodaki temel varlıklardır.
- Anahtarları seç: Her varlığı benzersiz tanımlayacak kimlik alanını belirle. Öğrenci için öğrenci kimliği, ders için ders kimliği düşünülebilir.
- İlişkileri ve cardinality’yi belirle: Varlıkların birbirleriyle kaç kayıt üzerinden bağlanabildiğini analiz et.
- Tabloları üret: Varlıkları tablolara, özellikleri sütunlara ve bağlantıları foreign key alanlarına dönüştür.
- Tutarlılık kontrolü yap: Geçersiz öğrenci-ders bağlantıları, eksik kayıtlar ve tekrarlı ilişkiler oluşup oluşamayacağını denetle.
Bu akışın önemli tarafı, SQL kodunun dördüncü aşamada gelmesidir. Yani CREATE TABLE yazmak başlangıç değil, daha önce alınmış modelleme kararlarının teknik karşılığıdır.
Görsel diyagram yoksa ER yapısı metinle nasıl gösterilir?
Bir diyagram görsel olarak paylaşılamadığında temel sembolleri metinle açıklamak mümkündür. Entity, yani varlık, kutu ile; attribute, yani özellik, kutunun içindeki alan adlarıyla; ilişki ise ok veya bağlantı sembolleriyle gösterilebilir.
[ÖĞRENCİ]
- ogrenci_id
- ad
- soyad
[ÖĞRENCİ] 1 ---- N [KAYIT] N ---- 1 [DERS]
Bu gösterimde kutular varlıkları temsil eder. ogrenci_id, ad ve soyad öğrenci varlığının özellikleridir. Öğrenci ile kayıt arasındaki 1 ---- N ifadesi, bir öğrencinin birden fazla kayıt satırına sahip olabileceğini anlatır. Kayıt ile ders arasındaki bağlantı ise her kayıt satırının bir derse ait olduğunu gösterir.
Metin tabanlı gösterim, görsel diyagram kadar ayrıntılı olmayabilir; ancak kararları kontrol etmek için yeterlidir. Özellikle bir projeye başlamadan önce varlıkları ve bağlantıları birkaç satırla yazmak, düşünülmemiş ilişkileri fark etmeyi kolaylaştırır.
Entity, attribute, primary key, foreign key ve cardinality nasıl anlaşılır?

ER diyagramını okuyabilmek için beş temel kavramı birbirinden ayırmak gerekir: entity, attribute, primary key, foreign key ve cardinality. Bu kavramlar yalnızca teorik terimler değildir; SQL tablosundaki satırların, sütunların ve bağlantıların hangi kurallara göre oluşturulacağını belirler.
Entity: Sistemde ayrı izlenen varlık
Entity, sistem içinde kendi başına anlam taşıyan ve ayrı olarak izlenmesi gereken nesnedir. Öğrenci-ders-kayıt örneğinde öğrenci ve ders açık birer entity’dir. Kayıt da iki varlık arasındaki katılım bilgisini temsil ettiği için ayrı bir entity olarak ele alınır.
Bir kavramın entity olup olmadığını anlamak için şu soruyu sorabilirsiniz: “Bu nesne hakkında birden fazla bilgi saklayacak mıyım ve bu nesneyi sistem içinde ayrı olarak takip edecek miyim?”
Örneğin şu kavramlar entity olabilir:
- Öğrenci: Ad, soyad, e-posta veya kayıt tarihi gibi bilgileri vardır.
- Ders: Ders adı, ders kodu ve kredi gibi bilgileri vardır.
- Kayıt: Hangi öğrencinin hangi derse ne zaman bağlandığını tutar.
Her isim mutlaka entity değildir. “Öğrencinin adı” tek başına entity değil, öğrenci varlığının bir özelliğidir. “Dersin adı” da ders varlığının attribute alanıdır.
Attribute: Varlığın özelliği
Attribute, bir entity hakkında saklanan özelliktir. SQL tarafında çoğunlukla sütun olarak karşılık bulur. Öğrenci entity’sinin ogrenci_id, ad ve soyad alanları olabilir. Ders entity’sinin ise ders_id, ders_adi ve ders_kodu alanları bulunabilir.
Bir alanı attribute olarak belirlerken yalnızca ekranda görünüp görünmediğine bakmayın. Uygulamanın karar vermesi, arama yapması veya kayıtları birbirinden ayırması için gereken bilgileri de düşünün. Örneğin kayıt tarihini ekranda hemen göstermeseniz bile, öğrencinin derse ne zaman katıldığını takip etmek için bu alan gerekli olabilir.
Primary key: Her kaydın kimlik kuralı
Primary key, bir tablodaki her kaydı benzersiz biçimde tanımlayan alandır veya alan grubudur. Öğrenci tablosunda iki kişinin adı ve soyadı aynı olabilir; ancak her öğrencinin kimliği birbirinden ayrılabilmelidir. Bu nedenle yalnızca ad alanı güvenilir bir kimlik değildir.
Birincil anahtar yalnızca teknik amaçla eklenen bir sütun değildir. Tablo tasarımının kimlik kuralını belirler. “Bu satırı diğer tüm satırlardan nasıl ayıracağım?” sorusuna verilen cevaptır.
Öğrenci-ders-kayıt sisteminde örnek bir kimlik yapısı şöyle düşünülebilir:
ogrenciler.ogrenci_id: Öğrenciyi benzersiz tanımlar.dersler.ders_id: Dersi benzersiz tanımlar.kayitlar.kayit_id: Kayıt satırını benzersiz tanımlar.
Bazı tasarımlarda kayıt tablosunda öğrenci ve ders ikilisinin birlikte benzersiz olması da istenebilir. Böyle bir kural, aynı öğrencinin aynı derse yanlışlıkla birden fazla kez eklenmesini önlemek için ayrıca değerlendirilebilir. Bu karar, sistemin gerçek iş kuralına göre verilmelidir.
Foreign key: Tablolar arasındaki bağlantı
Foreign key, bir tablodaki alanın başka bir tablonun primary key alanına referans vermesidir. Bu alan, tablolar arasındaki bağlantının SQL karşılığıdır.
Örneğin kayitlar tablosunda ogrenci_id ve ders_id alanları bulunabilir. İlk alan öğrenciler tablosundaki ogrenci_id değerine, ikinci alan dersler tablosundaki ders_id değerine bağlanır. Böylece kayıt satırı “hangi öğrenci, hangi derse bağlı?” sorusunu cevaplar.
CREATE TABLE kayitlar (
kayit_id INTEGER PRIMARY KEY,
ogrenci_id INTEGER NOT NULL,
ders_id INTEGER NOT NULL,
FOREIGN KEY (ogrenci_id) REFERENCES ogrenciler(ogrenci_id),
FOREIGN KEY (ders_id) REFERENCES dersler(ders_id)
);
Burada kayitlar tablosu tek başına öğrenci adını veya ders adını tekrar saklamak zorunda değildir. Bağlantı alanları üzerinden ilgili tablolara ulaşılır. Foreign key, yalnızca veri çekmeyi değil, geçersiz bir bağlantının oluşmasını önlemeyi de amaçlar.
Cardinality: Bir varlık kaç kayıtla ilişkilidir?
Cardinality, bir varlığın diğer varlıkla kaç kayıt üzerinden ilişki kurabildiğini anlatır. Bu kavramı anlamanın en kolay yolu, ilişkiyi iki yönden soru sormaktır.
- Bir öğrenci kaç derse kayıt olabilir?
- Bir dersin kaç öğrencisi olabilir?
- Bir kayıt hangi iki varlığı bağlar?
Öğrenci-ders-kayıt sisteminde bir öğrenci birden fazla derse kayıt olabilir. Aynı şekilde bir dersin birden fazla öğrencisi olabilir. Bu nedenle öğrenci ile ders arasında doğrudan tek bir bağlantı yerine kayıtları temsil eden ayrı bir yapı gerekir.
Cardinality kararını verirken “bugün uygulamada kaç kayıt var?” sorusundan çok, iş kuralının neye izin verdiğine bakın. Şu anda her öğrencinin yalnızca bir dersi olabilir; ancak sistemin amacı farklı derslere kayıt desteği vermekse ilişkiyi geçici örneğe göre değil, gerçek gereksinime göre tasarlamak gerekir.
Entity, attribute, primary key, foreign key ve cardinality kavramlarını pekiştirmek isteyen okuyucular, temel mantık ve problem çözme becerilerini gözden geçirmek için algoritma bilgi testi üzerinden pratik yapabilir.
İlişki türü nasıl seçilir: one-to-one, one-to-many ve many-to-many
İlişki türünü seçmenin pratik yolu, iki varlığın her iki yöndeki sınırını sormaktır: “A’dan kaç B olabilir?” ve “B’den kaç A olabilir?” Cevaplar, ilişkinin one-to-one, one-to-many veya many-to-many olduğunu gösterir.
| Soru | İlişki türü | Tabloya yansıması |
|---|---|---|
| Bir hesap en fazla bir ayar kaydına, bir ayar kaydı da yalnızca bir hesaba mı bağlı? | One-to-one | Foreign key taraflardan birinde bulunur ve benzersizlik kuralıyla sınırlandırılır. |
| Bir öğrenci birçok kayıt satırına, her kayıt satırı yalnızca bir öğrenciye mi bağlı? | One-to-many | Foreign key, çok olan taraftaki tabloda yer alır. |
| Bir öğrenci birçok derse, bir ders de birçok öğrenciye mi bağlanabiliyor? | Many-to-many | İki tablo arasına öğrenci ve ders foreign key’lerini taşıyan ara tablo eklenir. |
One-to-one ilişki
One-to-one ilişkide birinci varlığın bir kaydı, ikinci varlığın en fazla bir kaydıyla eşleşir. Aynı kural ters yönde de geçerlidir. Örneğin bir kullanıcı için tek bir profil kaydı veya bir hesabın tek bir ayar kaydı bulunabilir.
Bu ilişkide foreign key genellikle bağımlı olan tabloda tutulur. Örneğin profil tablosunda kullanici_id alanı bulunabilir. Ancak yalnızca foreign key tanımlamak yeterli olmayabilir; aynı kullanıcıya birden fazla profil eklenmesini engellemek için bu alanın benzersiz olması gerekir.
One-to-one seçmeden önce şu iki soruya da “en fazla bir” cevabı verebildiğinizden emin olun:
- Bir kullanıcı kaç profil kaydına sahip olabilir?
- Bir profil kaydı kaç kullanıcıya ait olabilir?
One-to-many ilişki
One-to-many ilişkide bir varlığın tek kaydı, diğer varlığın birden fazla kaydıyla eşleşebilir. Ancak çok olan taraftaki her kayıt, tek bir ana kayda bağlıdır.
Örneğin bir öğrenci birçok kayıt satırına sahip olabilir. Her kayıt satırı ise belirli bir öğrenciye aittir. Bu durumda ilişki öğrenci tarafından kayıtlara doğru one-to-many’dir. Foreign key, çok olan tarafta, yani kayitlar tablosunda bulunur.
Aynı mantık ders için de geçerlidir. Bir ders birçok kayıt satırı içerebilir; ancak her kayıt satırı tek bir dersi gösterir. Bu nedenle kayitlar.ders_id alanı dersler tablosuna bağlanır.
One-to-many ilişkide kullanılan temel düşünce şudur: “Çok olan kayıtların içinde, tek olan varlığın kimliği tutulur.” Öğrencinin içinde onlarca kayıt sütunu açmak yerine, her kayıt ayrı satır olarak tutulur.
Many-to-many ilişki
Many-to-many ilişkide her iki taraftaki bir kayıt, karşı tarafta birden fazla kayıtla eşleşebilir. Öğrenci-ders sistemi bunun klasik örneğidir:
- Bir öğrenci birçok derse kayıt olabilir.
- Bir ders birçok öğrenci içerebilir.
Bu ilişkiyi yalnızca ogrenciler tablosuna tek bir ders_id alanı ekleyerek çözemezsiniz. Böyle yaparsanız bir öğrencinin yalnızca tek bir dersi varmış gibi davranırsınız. Tersine, dersler tablosuna tek bir ogrenci_id eklemek de bir dersin yalnızca tek öğrencisi olmasına yol açar.
Çözüm, araya kayitlar adlı bir tablo koymaktır. Bu ara tablo, her öğrenci-ders eşleşmesini ayrı bir satır olarak saklar. Böylece bir öğrencinin farklı dersleri, bir dersin de farklı öğrencileri olabilir. Kayıt tarihi, not veya kayıt durumu gibi ilişkiye ait bilgiler de bu tabloda tutulabilir; çünkü bu bilgiler yalnızca öğrenciye ya da yalnızca derse değil, ikisinin oluşturduğu kayda aittir.
İlişki türünü belirlerken kısa karar kuralını kullanabilirsiniz:
- A’dan kaç B olabilir diye sor.
- B’den kaç A olabilir diye sor.
- İki cevap da bir ise one-to-one düşün.
- Bir taraf bir, diğer taraf çok ise one-to-many kur.
- İki taraf da çok ise ara tabloyla many-to-many tasarla.
Bu kararları vermeden tablo oluşturmaya başlamak, özellikle kayıt, sipariş-ürün, yazar-kitap veya kullanıcı-rol gibi yapılarda tekrar eden sütunlara ve zor yönetilen sorgulara yol açabilir. İlişki türü doğru belirlendiğinde primary key ve foreign key alanlarının hangi tabloda bulunacağı da büyük ölçüde netleşir.
Öğrenci-ders-kayıt sistemiyle ER diyagramı adım adım nasıl kurulur?
Öğrenci-ders-kayıt sistemi gibi bir projede ER diyagramı kurmanın en güvenli yolu, doğrudan tablo yazmaya başlamamaktır. Önce sistemdeki varlıkları çıkarır, her varlık için anahtarları seçer, ilişkileri ve cardinality’yi belirler, ardından tabloları üretir ve örnek senaryolarla tutarlılık kontrolü yaparsınız.
Bu akışta temel yapı şu şekilde kurulabilir: Öğrenci 1—N Kayıt N—1 Ders. Böylece bir öğrenci birçok kayıt oluşturabilir, bir ders de birçok öğrencinin kaydını içerebilir. Öğrenci ile ders arasındaki doğrudan many-to-many ilişki ise Kayıt varlığı üzerinden çözümlenir.
1. Varlıkları çıkarın
İlk aşamada sistemde bağımsız olarak saklanması gereken nesneleri belirleyin. Öğrenci-ders-kayıt senaryosunda üç temel entity bulunur:
- Student: Sisteme kayıtlı öğrenciyi temsil eder.
- Course: Öğrencilerin seçebileceği dersi temsil eder.
- Enrollment: Belirli bir öğrencinin belirli bir derse yaptığı kaydı temsil eder.
Burada önemli nokta, kayıt işleminin yalnızca “öğrenci” veya “ders” özelliği olmamasıdır. Kayıt, iki varlık arasındaki ilişkiyi temsil eden bağımsız bir entity’dir. Çünkü kayıt tarihi, not, devam durumu veya kayıt statüsü gibi bilgiler doğrudan öğrenciye ya da derse değil, öğrencinin o derse yaptığı belirli kayda aittir.
2. Anahtarları seçin
Her varlığın satırlarını birbirinden ayıran bir primary key alanı olmalıdır. Bu örnekte anahtarlar şu şekilde seçilebilir:
- StudentId: Her öğrenciyi benzersiz biçimde tanımlar.
- CourseId: Her dersi benzersiz biçimde tanımlar.
- EnrollmentId: Her kayıt işlemini benzersiz biçimde tanımlar.
Örneğin iki öğrencinin adı ve soyadı aynı olabilir. Bu nedenle öğrenciyi yalnızca adıyla ayırt etmek güvenli değildir. Benzer şekilde aynı isimde farklı dersler veya farklı dönemlerde açılan dersler bulunabilir. Primary key, bu belirsizliği ortadan kaldıran teknik kimliktir.
Enrollment tablosunda EnrollmentId bulunmasının yanında StudentId ve CourseId alanları da yer alır. StudentId, kaydın hangi öğrenciye ait olduğunu; CourseId ise hangi derse ait olduğunu gösterir.
3. İlişkileri ve cardinality’yi belirleyin
Şimdi varlıkların birbirleriyle nasıl ilişki kurduğunu iki yönden sorun:
- Bir öğrenci kaç kayıt oluşturabilir?
- Bir kayıt kaç öğrenciye ait olabilir?
- Bir ders kaç kayıt içerebilir?
- Bir kayıt kaç dersi temsil edebilir?
Gerçekçi bir öğrenci bilgi sisteminde bir öğrenci birden fazla derse kayıt olabilir. Her kayıt ise tek bir öğrenciye aittir. Bu nedenle Öğrenci ile Kayıt arasındaki ilişki one-to-many ilişkisidir:
Bir öğrenci → birçok kayıt
Bir kayıt → tek öğrenci
Aynı mantık dersler için de geçerlidir. Bir dersin birçok öğrencisi olabilir, ancak her kayıt yalnızca bir dersi temsil eder:
Bir ders → birçok kayıt
Bir kayıt → tek ders
Metinsel diyagram bu yapıyı şöyle gösterebilir:
Students 1 — N Enrollments N — 1 Courses
Bu gösterimde Enrollments tablosunun Students tablosuna doğru tarafında N, Courses tablosuna doğru tarafında da N bulunur. Öğrenci ile ders arasında doğrudan bakıldığında ise ilişki many-to-many’dir. Çünkü bir öğrenci birçok ders alabilir ve bir ders birçok öğrenci tarafından alınabilir. Enrollments, bu M—N ilişkiyi iki ayrı one-to-many ilişkiye bölen ara entity görevi görür.
4. İlişkiye ait alanları doğru entity’ye yerleştirin
EnrollmentDate ve Grade gibi alanlar öğrencinin genel bilgisi değildir. Bir öğrencinin farklı derslerde farklı kayıt tarihleri ve notları olabilir. Bu nedenle bu alanlar Students tablosuna eklenmemelidir.
Örneğin Ayşe öğrencisi Python dersine 10 Eylül’de, Java dersine ise 15 Eylül’de kayıt olmuş olabilir. Ayşe’nin tek bir kayıt tarihi alanı olsaydı bu iki farklı bilgiyi doğru biçimde saklamak mümkün olmazdı. Aynı şekilde Ayşe’nin Python notu ile Java notu farklı olabilir. Bu notları Students tablosunda tutmak, öğrenci başına tek not alanı gibi hatalı bir modele yol açar.
Doğru yerleşim şöyledir:
- Öğrencinin adı ve e-posta adresi: Students
- Dersin adı ve kodu: Courses
- Öğrencinin derse kayıt tarihi ve notu: Enrollments
5. Tabloları üretin ve örnek akışla kontrol edin
Son aşamada beklenen tablo yapısı aşağıdaki gibidir:
| Tablo | Temel alanlar | Görevi |
|---|---|---|
| Students | StudentId, Name, Email | Öğrenci bilgilerini saklar. |
| Courses | CourseId, CourseName | Ders bilgilerini saklar. |
| Enrollments | EnrollmentId, StudentId, CourseId, EnrollmentDate, Grade | Öğrenci-ders ilişkisini ve bu ilişkiye ait bilgileri saklar. |
Kısa bir senaryo üzerinden düşünelim. Bir öğrenci iki derse kayıt olsun ve bir ders iki farklı öğrenci tarafından alınsın:
- StudentId değeri 1 olan öğrenci, CourseId değeri 10 ve 20 olan iki derse kayıt olur.
- CourseId değeri 10 olan ders, StudentId değeri 1 ve 2 olan iki öğrencinin kaydını içerir.
- Bu dört ilişki bilgisi Enrollments tablosunda ayrı satırlar olarak tutulur.
Böylece hiçbir tabloya “öğrencinin aldığı dersler” gibi virgülle ayrılmış bir metin yazmak veya ders tablosuna yalnızca tek bir StudentId alanı eklemek gerekmez.
ER diyagramı SQL tablolarına nasıl dönüştürülür?

ER diyagramını SQL’e dönüştürürken temel kural, tabloları foreign key bağımlılıklarına göre oluşturmaktır. Önce bağımsız tablolar olan Students ve Courses hazırlanır. Daha sonra bu iki tabloya bağlanan Enrollments oluşturulur. Çünkü Enrollments içindeki StudentId ve CourseId alanları, önceden var olan tablolardaki primary key değerlerine referans verir.
İlk CRUD projesinde bu dönüşümü küçük parçalara ayırarak çalışmak, kavramlar arasındaki bağlantıyı görmek açısından yararlıdır. Örneğin canlı uygulamalarda veritabanı ilişkilerini öğrenirken uygulamalı yazılım eğitimleri içinde şema tasarımı, sorgu mantığı ve kod ile veritabanı arasındaki akış birlikte ele alınabilir.
Çalışabilir CREATE TABLE örneği
CREATE TABLE Students (
StudentId INTEGER PRIMARY KEY,
FullName VARCHAR(100) NOT NULL,
Email VARCHAR(150) NOT NULL UNIQUE
);
CREATE TABLE Courses (
CourseId INTEGER PRIMARY KEY,
CourseName VARCHAR(100) NOT NULL UNIQUE
);
CREATE TABLE Enrollments (
EnrollmentId INTEGER PRIMARY KEY,
StudentId INTEGER NOT NULL,
CourseId INTEGER NOT NULL,
EnrollmentDate DATE NOT NULL,
Grade DECIMAL(5, 2),
FOREIGN KEY (StudentId) REFERENCES Students(StudentId),
FOREIGN KEY (CourseId) REFERENCES Courses(CourseId),
UNIQUE (StudentId, CourseId)
);
Bu örnekte Students tablosunun her satırı StudentId ile ayırt edilir. FullName alanı boş bırakılamaz. Email alanındaki UNIQUE kısıtı ise aynı e-posta adresinin birden fazla öğrenci için kullanılmasını engellemek amacıyla eklenmiştir.
Courses tablosunda da CourseId primary key olarak kullanılır. CourseName alanındaki UNIQUE kısıtı, aynı ders adının tekrar tekrar eklenmesini önlemek için tercih edilmiştir. Gerçek bir sistemde aynı dersin farklı dönemlerde açılması gerekiyorsa dönem veya şube bilgisi ayrıca modellenebilir. Ancak temel öğrenci-ders-kayıt örneğinde bu ayrıntı gerekli değildir.
Foreign key alanları ilişkiyi nasıl korur?
Enrollments tablosunda iki foreign key bulunur:
- StudentId → Students(StudentId)
- CourseId → Courses(CourseId)
Bu bağlantılar sayesinde Enrollments tablosuna var olmayan bir öğrenciyi veya var olmayan bir dersi işaret eden kayıt eklenmesi engellenir. Örneğin Students tablosunda StudentId değeri 1 yoksa, StudentId değeri 1 olan yeni bir enrollment satırı geçerli bir ilişki kuramaz.
Enrollments tablosundaki UNIQUE (StudentId, CourseId) kuralı ise iki alanı birlikte değerlendirir. Aynı öğrenci aynı derse yalnızca bir kez kayıt olabilir. Buna karşılık farklı öğrenciler aynı derse, aynı öğrenci de farklı derslere kayıt olabilir.
Örnek veri ilişkisi nasıl okunur?
Tabloları oluşturduktan sonra örnek kayıtlar şu mantıkta düşünülebilir:
| EnrollmentId | StudentId | CourseId | EnrollmentDate | Grade |
|---|---|---|---|---|
| 100 | 1 | 10 | 2026-09-10 | 85.00 |
| 101 | 1 | 20 | 2026-09-12 | 92.00 |
| 102 | 2 | 10 | 2026-09-11 | 78.00 |
Bu sonuçlara göre StudentId değeri 1 olan öğrenci iki farklı derse kayıtlıdır. CourseId değeri 10 olan ders ise StudentId değerleri 1 ve 2 olan iki öğrenci tarafından alınmaktadır.
İlişkiyi öğrenci ve ders adlarıyla birlikte okumak için şu sorgu kullanılabilir:
SELECT
s.FullName,
c.CourseName,
e.EnrollmentDate,
e.Grade
FROM Enrollments e
JOIN Students s ON e.StudentId = s.StudentId
JOIN Courses c ON e.CourseId = c.CourseId;
Beklenen sonuç mantıksal olarak şu biçimdedir: “Ayşe, SQL Temelleri dersine 2026-09-10 tarihinde kayıt oldu ve notu 85.” Burada cümleyi oluşturan bilgiler üç farklı tablodan gelir; ilişkiyi birleştiren tablo ise Enrollments’tır.
Diyagramdan tabloya geçerken yapılan hatalar nasıl teşhis edilir?
ER diyagramı doğru görünse bile tabloya dönüşüm sırasında cardinality, anahtar veya alan yerleşimi hataları yapılabilir. Bu nedenle SQL kodunu çalıştırmadan önce tasarımı birkaç basit soruyla test etmek gerekir. En iyi teşhis yöntemi, her ilişkinin gerçek hayattaki senaryoyla karşılaştırılmasıdır.
Primary key eksik mi?
Her tablo için şu soruyu sorun: Her satırı tek başına ayırt edebiliyor muyum?
Students tablosunda yalnızca FullName alanı varsa iki farklı kişinin aynı isimle kaydedilmesi sorun yaratabilir. Courses tablosunda yalnızca CourseName kullanılması da aynı ders adının farklı kayıtlarla karışmasına neden olabilir. Bu nedenle her tabloda güvenilir bir primary key bulunmalı ve diğer tablolar bu anahtara referans vermelidir.
Cardinality yanlış mı kurulmuş?
İlişkinin iki yönünü ayrı ayrı değerlendirin:
- Bir öğrenci kaç derse kayıt olabilir?
- Bir ders kaç öğrenci tarafından alınabilir?
- Bir kayıt kaç öğrenciye bağlanabilir?
- Bir kayıt kaç dersi temsil edebilir?
Öğrenci-ders örneğinde öğrenciye tek bir CourseId alanı eklemek hatalıdır. Çünkü bu tasarım bir öğrencinin yalnızca bir dersi olduğunu varsayar. Öğrencinin ikinci, üçüncü veya daha fazla derse kaydolması gerektiğinde tek sütun yetersiz kalır.
Aynı hata ters yönde de yapılabilir. Courses tablosuna tek bir StudentId alanı eklemek, bir dersin yalnızca bir öğrencisi olabileceği anlamına gelir. Oysa dersin birçok öğrencisi olabilir. Bu nedenle StudentId ve CourseId alanları doğrudan Students veya Courses tablosuna sıkıştırılmak yerine Enrollments tablosunda birlikte tutulmalıdır.
Many-to-many ilişki çözülememiş mi?
Bir ilişkinin iki tarafında da “birden fazla” ifadesi geçiyorsa ara tablo ihtimalini kontrol edin. Öğrenci ve ders arasındaki many-to-many ilişki, Enrollments olmadan doğrudan ve düzenli biçimde saklanamaz.
Ara tablo yalnızca bağlantıyı kurmaz; ilişkinin kendi alanlarını da taşır. EnrollmentDate, Grade, AttendanceStatus veya RegistrationStatus gibi bilgiler bu tabloda bulunabilir. Çünkü bu alanların anlamı, öğrencinin genel özelliklerinden veya dersin genel özelliklerinden değil, belirli bir öğrenci-ders eşleşmesinden doğar.
Gereksiz veri tekrarı var mı?
Şu testi uygulayın: Aynı bilgi kaç satırda tekrar ediliyor?
Öğrenci adını her enrollment satırında saklamak gereksiz tekrara yol açar. Ayşe iki derse kayıtlıysa adı iki satırda tekrar eder; ad değiştiğinde bu satırların tamamının güncellenmesi gerekir. Bir satırın güncellenip diğerinin unutulması tutarsız veri üretir.
Benzer şekilde ders adını Enrollments tablosunda tekrar tekrar yazmak yerine CourseId saklanmalıdır. Ders adı gerektiğinde JOIN kullanılarak Courses tablosundan alınabilir. Böylece temel bilgiler tek bir yerde korunur, kayıt tablosu ise ilişkiye ait alanlara odaklanır.
Foreign key doğru tabloya mı yerleştirilmiş?
One-to-many ilişkilerde foreign key çoğunlukla “çok” tarafındaki tabloda bulunur. Bu örnekte bir öğrenci birçok enrollment satırına sahip olduğu için StudentId, Enrollments tablosunda yer alır. Aynı şekilde CourseId de Enrollments tablosundadır.
Nullable alanları da ilişkinin zorunluluğuyla karşılaştırın. Her enrollment mutlaka bir öğrenciye ve bir derse bağlıysa StudentId ile CourseId alanlarının NULL kabul etmemesi gerekir. Grade alanı ise not henüz verilmeden önce boş kalabilecekse nullable bırakılabilir. Burada alanın boş kalıp kalamayacağı, iş kuralına göre belirlenmelidir.
İlişki tablosunda iki anahtarı birlikte değerlendirmeyi de unutmayın. EnrollmentId her kayıt satırını ayırır; fakat aynı öğrencinin aynı derse ikinci kez eklenmesini engellemek için StudentId ve CourseId ikilisi üzerinde ayrıca bileşik UNIQUE kısıtı gerekebilir.
Tasarımınızı uygulamadan önce temel SQL ve ilişki mantığınızı kodlama bilgisi testi üzerinden gözden geçirmek, hangi kavramları tekrar etmeniz gerektiğini fark etmenize yardımcı olabilir.
ER tasarım kontrol listesi
- Tüm varlıklar belirlendi mi?
- Her tabloda bir primary key bulunuyor mu?
- Foreign key yönü doğrulandı mı?
- Cardinality gerçek senaryoyla uyuşuyor mu?
- Many-to-many ilişkilerde ara tablo kullanıldı mı?
- İlişkiye ait alanlar doğru tabloda tutuluyor mu?
- Örnek CRUD işlemlerinin tasarımı bozmayacağı kontrol edildi mi?
Bu kontrolün son maddesi özellikle önemlidir. Yeni öğrenci ekleme, ders oluşturma, kayıt silme, not güncelleme ve öğrencinin derslerini listeleme gibi temel işlemleri zihninizde veya küçük sorgularla deneyin. Bir işlem sırasında aynı bilgiyi birçok yerde değiştirmek zorunda kalıyorsanız ya da yeni bir ilişki eklemek için mevcut verileri metin olarak parçalamanız gerekiyorsa ER tasarımını yeniden inceleyin.
İlk CRUD projesi için uygulanabilir ER tasarım çalışma planı
İlk CRUD projenizde doğrudan ekran veya API koduna geçmek yerine önce veritabanının iskeletini netleştirin. Uygulanabilir sıra şudur: varlıkları çıkarın → anahtarları seçin → ilişkileri ve cardinality’yi belirleyin → tabloları üretin → tutarlılık kontrolü yapın. Bu akış, öğrenci-ders-kayıt örneğini görev, sipariş, ürün veya kullanıcı yönetimi gibi farklı projelere taşımanızı sağlar.
Örneğin bir görev takip uygulamasında kullanıcı, görev ve etiket varlıklarını; basit bir satış uygulamasında müşteri, ürün ve sipariş varlıklarını; öğrenci bilgi sisteminde ise öğrenci, ders ve kayıt varlıklarını ele alabilirsiniz. Projenin konusu değişse de tasarım soruları büyük ölçüde aynı kalır.
ER diyagramı ve tablo tasarımı konusunda farklı örnekleri inceleyerek ilerlemek isterseniz, yazılım geliştirme blog içerikleri içindeki proje ve programlama odaklı yazılardan yararlanabilirsiniz. Buradaki amaç hazır bir şablonu kopyalamak değil, her projede aynı düşünme alışkanlığını uygulamaktır.
1. Varlıkları listeleyin
İlk adımda henüz sütun veya SQL kodu düşünmeden, sistemde hakkında bilgi saklanacak temel nesneleri yazın. Bir varlık genellikle uygulamanın “kim, ne veya hangi olay?” sorularından birine cevap verir.
- Öğrenci-ders sistemi: Öğrenci, Ders, Kayıt
- Görev takip sistemi: Kullanıcı, Görev, Etiket
- Sipariş sistemi: Müşteri, Sipariş, Ürün, Sipariş Kalemi
- Kütüphane sistemi: Üye, Kitap, Ödünç İşlemi
Her isim ayrı bir tablo olmak zorunda değildir. Örneğin “adres” bazı projelerde bağımsız bir varlık, bazı projelerde ise kullanıcı tablosunun birkaç alanı olabilir. Bu kararı, adresin kendi başına yönetilip yönetilmediğine göre verin. Bir nesne için ayrı ayrı ekleme, güncelleme, silme veya ilişkilendirme işlemleri yapılacaksa bağımsız varlık olma ihtimali artar.
2. Her varlık için kimlik alanını seçin
Her tablo için birincil anahtar belirleyin. Bu alan, tablodaki her kaydı diğerlerinden ayırmalıdır. Başlangıç projelerinde çoğu zaman student_id, course_id veya task_id gibi sayısal ve otomatik artan kimlikler tercih edilir.
Kimlik alanı seçerken şu soruları sorun:
- Bu alan her kayıt için benzersiz olacak mı?
- Değeri zaman içinde değişebilir mi?
- Başka tablolar bu kayda güvenilir biçimde bağlanabilir mi?
- Kimlik alanı boş bırakılabilir mi?
Örneğin öğrencinin e-posta adresi benzersiz görünse bile e-posta değişebilir. Bu nedenle e-postayı birincil anahtar yapmak yerine ayrı bir alan olarak tutmak, gerekiyorsa UNIQUE kısıtı eklemek genellikle daha güvenli bir tasarımdır. Birincil anahtarın görevi yalnızca “benzersiz görünen bir bilgi” taşımak değil, kaydın kalıcı kimliğini sağlamaktır.
3. İlişkileri iki yönlü sorularla sınıflandırın
İki varlık arasındaki ilişkiyi tek yönden düşünmek yerine iki yönlü sorularla test edin. Öğrenci-ders-kayıt sistemi için şu soruları sorun:
- Bir öğrenci kaç derse kayıt olabilir?
- Bir ders kaç öğrenciyi içerebilir?
- Bir öğrencinin aynı derse birden fazla aktif kaydı olabilir mi?
- Kayıt tarihi ve not gibi bilgiler öğrenciye mi, derse mi, yoksa ikisini bağlayan olaya mı aittir?
İlk iki sorunun cevabı “bir öğrenci birçok derse, bir ders de birçok öğrenciye bağlanabilir” ise ilişki many-to-many’dir. Bu durumda doğrudan öğrenci tablosuna ders kimliği, ders tablosuna da öğrenci kimliği eklemek yerine ilişkiyi temsil eden enrollments gibi bir ara tablo oluşturulur.
Aynı yöntemi kendi projenizde de kullanabilirsiniz:
- Bir kullanıcı kaç görev oluşturabilir, bir görev kaç kullanıcıya atanabilir?
- Bir sipariş kaç ürün içerebilir, bir ürün kaç siparişte bulunabilir?
- Bir müşteri kaç adrese sahip olabilir, bir adres kaç müşteriye ait olabilir?
Cevaplar ilişkinin yönünü ve cardinality’sini belirler. Özellikle “bir taraftaki kayıt diğer tarafta kaç kayıtla eşleşebilir?” sorusu, yabancı anahtarın hangi tabloda bulunacağını anlamayı kolaylaştırır.
4. Many-to-many durumunda ara tablo arayın
İki tablo arasında many-to-many ilişki gördüğünüzde, ilişkiyi ayrı bir varlık gibi ele alın. Öğrenci-ders örneğinde bu varlık “kayıt” işlemidir. Kayıt, yalnızca iki kimliği birleştirmez; kayıt tarihi, dönem, durum veya not gibi ilişkiye ait bilgileri de taşıyabilir.
Bu nedenle şu yapı daha anlamlıdır:
students: Öğrenciye ait bilgilercourses: Derse ait bilgilerenrollments: Hangi öğrencinin hangi derse ne zaman ve hangi durumla bağlandığı
Bir ara tablonun temelinde genellikle iki yabancı anahtar bulunur. Aynı öğrencinin aynı derse iki kez eklenmesini önlemek için bu iki alanın birlikte benzersiz olması da sağlanabilir. Böylece hem veri tekrarı hem de hatalı kayıt ihtimali azalır.
5. Tabloları CREATE TABLE ile üretin
Varlıkları ve ilişkileri belirledikten sonra SQL kodunu yazın. Aşağıdaki örnek, öğrenci-ders-kayıt sisteminin temel ve doğrudan çalıştırılabilir bir taslağıdır:
CREATE TABLE students (
student_id INTEGER PRIMARY KEY,
full_name VARCHAR(100) NOT NULL
);
CREATE TABLE courses (
course_id INTEGER PRIMARY KEY,
course_name VARCHAR(100) NOT NULL
);
CREATE TABLE enrollments (
student_id INTEGER NOT NULL,
course_id INTEGER NOT NULL,
enrolled_at DATE NOT NULL,
grade DECIMAL(4,2),
PRIMARY KEY (student_id, course_id),
FOREIGN KEY (student_id) REFERENCES students(student_id),
FOREIGN KEY (course_id) REFERENCES courses(course_id)
);
Bu tasarımda students ve courses tabloları kendi birincil anahtarlarına sahiptir. enrollments tablosu ise iki tabloya yabancı anahtarlarla bağlanır. PRIMARY KEY (student_id, course_id) ifadesi, aynı öğrencinin aynı derse birden fazla kez eklenmesini engelleyen birleşik birincil anahtardır.
Kullanılan kimlik üretim yöntemi veritabanı sistemine göre değişebilir. Bazı sistemlerde otomatik artan alanlar için farklı sözdizimleri bulunur. Bu nedenle belirli bir veritabanı motoruna geçmeden önce o motorun veri türleri ve kimlik üretimi kuralları kontrol edilmelidir. Ancak ER mantığı değişmez: varlıkların kimlikleri, ilişkilerin yabancı anahtarları ve ilişkiye ait alanlar doğru yerde tutulmalıdır.
6. CRUD senaryolarıyla tasarımı test edin
Tablolar oluşturulduktan sonra yalnızca kodun hata vermediğini kontrol etmek yeterli değildir. Tasarımın gerçek kullanım akışlarını taşıyıp taşımadığını test edin. Her temel varlık ve ilişki için en az bir ekleme, listeleme, güncelleme ve silme senaryosu hazırlayın.
- Create: Bir öğrenci, bir ders ve bu öğrencinin derse kaydını ekleyin.
- Read: Bir öğrencinin kayıtlı olduğu dersleri listeleyin.
- Update: Öğrencinin notunu veya kayıt durumunu güncelleyin.
- Delete: Bir kaydı silin ve ilgili öğrenci ile ders bilgilerinin yanlışlıkla silinmediğini kontrol edin.
Bu testlerde özellikle sınır durumlarını deneyin. Olmayan bir öğrenci için kayıt eklemeyi, olmayan bir derse bağlanmayı, aynı öğrenciyi aynı derse ikinci kez kaydetmeyi ve boş bırakılmaması gereken alanları kontrol edin. Foreign key ve NOT NULL gibi kısıtlar, bu hataların bir bölümünü uygulama koduna ulaşmadan veritabanı seviyesinde yakalar.
7. API ve arayüzden önce veri modelini netleştirin
İlk CRUD projesinde kullanıcı arayüzünü hızlıca hazırlamak cazip gelebilir. Ancak tablo ilişkileri netleşmeden yazılan API uçları ve form kodları, daha sonra kapsamlı değişikliklere yol açabilir. Örneğin kayıt tarihi yanlış tabloya konulursa sorgular karmaşıklaşır; ders kimliği öğrenci tablosuna eklenirse bir öğrencinin birden fazla dersini yönetmek zorlaşır.
Veri modelini önce netleştirmek, hata ayıklamayı birkaç yönden kolaylaştırır:
- Hatanın arayüzde mi, API’de mi, yoksa veri tabanı kısıtında mı olduğunu ayırabilirsiniz.
- Her endpoint’in hangi tabloyu ve ilişkiyi kullandığı daha açık olur.
- Listeleme sorgularında gerekli JOIN işlemleri önceden anlaşılır.
- Güncelleme ve silme işlemlerinin hangi kaydı etkileyeceği belirginleşir.
- Test verisi oluşturmak ve beklenen sonucu karşılaştırmak kolaylaşır.
Bu aşamadan sonra uygulama katmanında öğrenci ekleme, ders listeleme veya kayıt oluşturma gibi işlemler daha kontrollü biçimde geliştirilebilir. Veritabanı şeması değişirse bunun API sözleşmesine ve arayüz formlarına etkisini de önceden görebilirsiniz.
Kısa ER tasarım kontrol listesi
- Projede bilgi saklanan temel varlıkları ayrı ayrı listeledim mi?
- Her tablo için kararlı ve benzersiz bir primary key seçtim mi?
- Her ilişkinin iki yönünü ayrı ayrı sordum mu?
- One-to-one, one-to-many ve many-to-many ayrımını gerekçelendirdim mi?
- Many-to-many ilişkiler için ara tablo gerekip gerekmediğini kontrol ettim mi?
- İlişkiye ait alanları doğru tabloya yerleştirdim mi?
- Foreign key, NOT NULL ve UNIQUE gibi kısıtları gerekli yerlerde kullandım mı?
- CREATE, READ, UPDATE ve DELETE senaryolarını denedim mi?
- Hatalı veya eksik verilerin veritabanına girmesini test ettim mi?
- API ve arayüz geliştirmeden önce şemayı açıklayabiliyor muyum?
Bu listeyi her yeni CRUD projesinde yeniden kullanabilirsiniz. Tasarımın amacı yalnızca tabloları oluşturmak değil, uygulamanın gerçek işlemlerini tutarlı ve anlaşılır biçimde taşıyan bir yapı kurmaktır.
Sık Sorulan Sorular
ER diyagramı çizmeden doğrudan SQL tablosu oluşturmak neden sorun çıkarabilir?
ER diyagramı olmadan doğrudan tablo yazmak, varlıkların ve ilişkilerin yanlış yerde modellenmesine yol açabilir. Özellikle many-to-many ilişkilerde bir tabloya tekrar tekrar sütun eklemek, veri tekrarına ve sorgu karmaşasına neden olur. Diyagram, SQL kodundan önce hangi varlıkların bulunduğunu, tabloların nasıl bağlandığını ve ilişkinin cardinality’sini görünür hâle getirir.
Many-to-many ilişki neden ara tablo ile modellenir?
Many-to-many ilişkide birinci tablodaki bir kayıt, ikinci tablodaki birçok kayıtla; ikinci tablodaki bir kayıt da birinci tablodaki birçok kayıtla eşleşebilir. Bu bağlantıları doğrudan iki tabloya yerleştirmek tekrar eden veya sınırsız sayıda alan gerektirir. Ara tablo, her eşleşmeyi ayrı bir satır olarak saklar ve kayıt tarihi, not, miktar veya durum gibi ilişkiye ait bilgilerin tutulmasını sağlar.
Primary key ile foreign key arasındaki temel fark nedir?
Primary key, bulunduğu tablodaki kaydı benzersiz biçimde tanımlar. Foreign key ise bir tablodaki kaydı başka bir tablodaki primary key’e bağlar. Örneğin students.student_id öğrenciyi tanımlarken, enrollments.student_id ilgili kaydın hangi öğrenciye ait olduğunu gösterir.
Bir ilişkinin one-to-one mı yoksa one-to-many mi olduğunu nasıl anlarım?
İlişkinin her iki tarafı için “bir kayıt diğer tarafta kaç kayıtla eşleşebilir?” sorusunu sorun. Bir kullanıcı yalnızca tek bir profil kaydına sahip olabiliyor ve bir profil yalnızca tek kullanıcıya ait olabiliyorsa ilişki one-to-one’dır. Bir müşteri birçok sipariş verebiliyor, fakat her sipariş yalnızca bir müşteriye ait oluyorsa ilişki one-to-many’dir.
Öğrenci-ders-kayıt örneğinde kayıt tarihi ve not bilgisi hangi tabloda tutulmalıdır?
Kayıt tarihi ve not, öğrencinin veya dersin tek başına özelliği değildir; öğrencinin belirli bir derse yaptığı kayıtla ilgilidir. Bu nedenle iki varlığı bağlayan enrollments tablosunda tutulmalıdır. Böylece aynı öğrenci farklı derslerde farklı tarihlere ve notlara sahip olabilir.
İyi bir ER tasarımı, CRUD projesinin yalnızca veritabanı bölümünü değil, sorgulardan API uçlarına ve kullanıcı arayüzüne kadar tüm geliştirme sürecini daha anlaşılır hâle getirir.