İlişkisel model, anahtarlar ve ER'den tabloya
İlişki, şema, örnek, domain; super/candidate/primary/foreign key; referans bütünlüğü ve ER diyagramını tablolara çevirme kuralları. Hem cebir hem SQL soruları bu tablolara dayanır.
ER diyagramı kağıt üzerindeki tasarımdı. İlişkisel model (relational model) onun bilgisayardaki karşılığı: her şey tablo. Bu hafta iki şey öğreniyorsun. Birincisi terminoloji ve anahtarlar; ilişkisel cebir, SQL ve normalizasyon bu kavramların üzerine kurulu, “candidate key nedir” bilmeden 9. haftayı geçemezsin. İkincisi ER’den tabloya çevirme kuralları; vizede neredeyse her yıl “bu diyagramı ilişki şemalarına dönüştür” sorusu çıkar.
Altın kurallar:
- Şema sabit, örnek değişken. Kısıtlar şemaya aittir.
- Anahtar minimal olmalı. Fazladan öznitelik varsa süper anahtardır, aday değil.
- FK başvurduğu satırın var olmasını şart koşar. Ya değer gerçek bir PK’ya eşittir ya NULL’dır.
- M:N her zaman ayrı tablo. 1:N, N tarafına kolon olur.
Terminoloji
İlişkisel modelde veri tablolarda durur. Matematiksel adıyla tablo bir ilişkidir (relation), satır bir tuple, kolon bir özniteliktir (attribute). Kursta kullandığımız student ilişkisi:
| stu_id | name | dept_name | tot_cred |
|---|---|---|---|
| S1 | Ada | CS | 60 |
| S2 | Bora | CS | 30 |
| S3 | Cem | EE | 45 |
| S4 | Defne | MATH | 90 |
| S5 | Ece | CS | 15 |
| S6 | Firat | EE | 0 |
| S7 | Gizem | NULL | 10 |
- Domain: bir özniteliğin alabileceği değerler kümesi.
tot_crediçin negatif olmayan tam sayılar. - Atomiklik (atomicity): her hücrede tek, bölünmez bir değer. Bir hücreye “555-0101, 555-0102” yazmak ilişkisel modeli bozar; bu, 1NF’nin (9. hafta) temelidir.
- NULL: değer bilinmiyor ya da yok. S7’nin bölümü henüz belli değil.
- Derece (degree): öznitelik sayısı, burada 4. Kardinalite: tuple sayısı, burada 7.
İlişki bir kümedir: satırların sırası yoktur ve iki aynı satır olamaz. Kolon sırası da teoride önemsizdir, çünkü öznitelikler isimle çağrılır.
Şema ve örnek
İlişki şeması (relation schema), ilişkinin yapısıdır: student(stu_id, name, dept_name, tot_cred). İlişki örneği (relation instance), belli bir andaki satırlardır. Programlamadaki karşılığı: şema değişken tipi, örnek değişkenin o anki değeri. Ada mezun olunca örnek değişir, şema aynı kalır.
Tüm kurs boyunca kullanacağımız şemalar:
department (dept_name, building, budget)
instructor (inst_id, name, dept_name -> department, salary)
student (stu_id, name, dept_name -> department, tot_cred)
course (course_id, title, dept_name -> department, credits)
teaches (inst_id -> instructor, course_id -> course)
takes (stu_id -> student, course_id -> course, grade)
Altı çizili yazamadığımız için birincil anahtar ilk kolon(lar); teaches ve takes için ilk iki kolon birlikte. Ok -> foreign key’in nereye baktığını gösterir. Şema diyagramında (schema diagram) her tablo bir kutu, PK altı çizili, FK’lar başvurdukları tablonun PK’sına okla bağlanır.
Anahtarlar
Süper anahtar (superkey): değerleri her satırı tekil belirleyen öznitelik kümesi. student için {stu_id}, {stu_id, name}, {stu_id, name, dept_name, tot_cred} hepsi süper anahtar.
Aday anahtar (candidate key): minimal süper anahtar, yani hiçbir özniteliği çıkarılamayan. {stu_id} aday; {stu_id, name} değil, çünkü name’i atınca hâlâ anahtar.
Birincil anahtar (primary key): tasarımcının aday anahtarlar arasından seçtiği. Bir ilişkinin birden fazla aday anahtarı olabilir (öğrenci numarası ve TC kimlik no); birini PK seçersin, diğerine UNIQUE koyarsın.
Yabancı anahtar (foreign key): bir ilişkideki öznitelik(ler)in, başka (ya da aynı) ilişkinin PK’sına başvurması. takes.stu_id → student.stu_id. Başvuran ilişki referencing, başvurulan referenced relation.
Örnekten anahtar okumak
Bir kümenin örnekte tekrar içerip içermediğine SQL ile bakabilirsin:
SELECT stu_id, course_id FROM takes
GROUP BY stu_id, course_id HAVING COUNT(*) > 1; -- boş: tekrar yok
SELECT stu_id, grade FROM takes
GROUP BY stu_id, grade HAVING COUNT(*) > 1; -- 3 grup tekrarlı
(ilk sorgu: satır yok)
S1 | A
S1 | B
S4 | A
TUZAK · örnek veri anahtar ispatlamaz.
nameşu anki 7 öğrencide tekrarsız, ama anahtar değil: ikinci bir “Ada” kaydolabilir. Örnek ancak olumsuz kanıt verir:dept_nametekrarlı (CS üç kez), o halde kesinlikle anahtar değil. Sınavda “this instance” ile “the schema” ayrımına dikkat.
Süper anahtar sayma
Bir öznitelik kümesi, en az bir aday anahtarı içeriyorsa süper anahtardır. R(A, B, C, D) için tek aday anahtar {A} ise geri kalan üç öznitelik istediğin gibi eklenir: süper anahtar. İki aday anahtar {A} ve {B, C} varsa içerme-dışarma uygula:
Son terim hem A’yı hem B,C’yi içerenler: {A,B,C} ve {A,B,C,D}.
Bütünlük kısıtları ve referans bütünlüğü
- Varlık bütünlüğü (entity integrity): PK değeri tekrar edemez ve NULL olamaz.
- Referans bütünlüğü (referential integrity): FK değeri ya NULL’dır ya da başvurulan tabloda gerçekten var olan bir PK değeridir.
Örnek veritabanında PRAGMA foreign_keys = ON ile denediklerimiz:
| İşlem | Sonuç | Neden |
|---|---|---|
INSERT INTO takes VALUES ('S9','CS101','A') | reddedildi | S9 diye öğrenci yok |
INSERT INTO instructor VALUES ('I7','Ozturk','PHYS',65000) | reddedildi | PHYS bölümü yok |
INSERT INTO student VALUES ('S8','Hakan',NULL,0) | kabul | FK NULL olabilir |
INSERT INTO student VALUES ('S1','Zeynep','CS',0) | reddedildi | PK tekrarı |
DELETE FROM department WHERE dept_name='CS' | reddedildi | hoca, öğrenci, ders CS’ye başvuruyor |
| S5’in takes satırlarını silip sonra S5’i silmek | kabul | artık başvuran yok |
Başvurulan satır silinirken ne olacağını FK tanımında seçersin: varsayılan NO ACTION/RESTRICT reddeder, ON DELETE CASCADE başvuranları da siler, ON DELETE SET NULL FK’yı NULL yapar.
TUZAK · SQLite ve NULL birincil anahtar. Standart SQL’de PK asla NULL olamaz. SQLite tarihsel bir hata yüzünden
TEXT PRIMARY KEYkolonuna NULL kabul ediyor (doğrulamada denendi);NOT NULLeklersen reddeder. Ayrıca SQLite’ta FK kontrolü varsayılan kapalıdır,PRAGMA foreign_keys = ONgerekir. PostgreSQL ve MySQL (InnoDB) bunları kendiliğinden uygular.
ER’den ilişkisel şemaya çevirme kuralları
| ER yapısı | Tabloya nasıl geçer |
|---|---|
| Güçlü varlık | Kendi tablosu; basit öznitelikler kolon, anahtar PK |
| Bileşik öznitelik | Sadece yaprak parçalar kolon: name → first_name, last_name |
| Çok değerli öznitelik | Ayrı tablo: inst_phone(inst_id, phone), PK ikisi birden, inst_id FK |
| Türetilmiş öznitelik | Kolon olmaz (gerekirse view ile hesaplanır) |
| Zayıf varlık | Tablo; sahip PK’sı FK olarak eklenir, PK = sahip PK + discriminator |
| Tanımlayıcı ilişki | Tablo olmaz, zayıf varlığın tablosunda zaten var |
| 1:N ilişki | N tarafına “1” tarafın PK’sı FK kolonu olarak; ilişki öznitelikleri de N tarafına |
| Total katılım (N tarafı) | O FK kolonu NOT NULL |
| 1:1 ilişki | Bir tarafa FK + UNIQUE (tercihen total katılan tarafa), ya da ayrı tablo |
| M:N ilişki | Ayrı tablo: iki PK + ilişki öznitelikleri, PK = iki PK birleşimi |
| n’li (ternary) ilişki | Ayrı tablo: tüm katılımcıların PK’ları |
Çözümlü örnek
Senaryo: department; instructor (bileşik name, çok değerli phone, bölüme N:1 total); student (bir danışman hoca, 1:N); course; section (course’un zayıf varlığı); takes (student ile section arasında M:N, grade); dean (department ile instructor arasında 1:1, ayrı tabloda tutulacak).
department (dept_name, building)
instructor (inst_id, first_name, last_name, dept_name -> department NOT NULL)
inst_phone (inst_id -> instructor, phone) PK: ikisi
student (stu_id, name, advisor_id -> instructor)
course (course_id, title)
section (course_id -> course, sec_id, semester, year) PK: dördü
takes (stu_id -> student, course_id, sec_id, semester, year, grade)
PK: ilk beşi ; FK (course_id, sec_id, semester, year) -> section
dean (dept_name -> department, inst_id -> instructor UNIQUE) PK: dept_name
Toplam 8 tablo. Şemayı SQLite’ta kurup denedik: olmayan şubeye kayıt bileşik FK yüzünden reddedildi, aynı hocayı iki bölüme dekan yapmak UNIQUE yüzünden reddedildi, bölümsüz hoca NOT NULL yüzünden reddedildi, ders silinince şubeleri CASCADE ile gitti.
Dikkat: takes bir section’a bağlandığı için FK dört kolonlu bir bileşik anahtardır. FK, başvurduğu PK’nın tüm kolonlarını içermek zorunda; sadece course_id’yi section’a bağlayamazsın.
Specialization için üç yol
person(pid, name) → student(tot_cred), employee(salary):
| Yöntem | Tablolar | Ne zaman |
|---|---|---|
| 1. Üst + alt tablolar | person(pid, name), student(pid, tot_cred), employee(pid, salary) | Her durumda çalışır; alt tabloların pid’si person’a FK |
| 2. Sadece alt tablolar | student(pid, name, tot_cred), employee(pid, name, salary) | Sadece total ve disjoint ise |
| 3. Tek tablo | person(pid, name, ptype, tot_cred, salary) | Az alt küme varsa; ilgisiz kolonlar NULL |
Yöntem 2 overlapping’de aynı kişinin name’ini iki kez saklar, partial’da hiçbir alt kümede olmayan kişiyi saklayamaz.
Sık yapılan hatalar
| Yanlış düşünce | Doğrusu |
|---|---|
| Derece = satır sayısı | Derece kolon, kardinalite satır sayısı |
| {stu_id, name} aday anahtar | Süper anahtar; minimal değil |
| Örnekte tekrar yok, o halde anahtar | Kısıt şemaya ait; örnek sadece çürütür |
| FK NULL olamaz | Olabilir; PK olamaz |
| FK aynı isimde olmalı | İsim serbest (advisor_id → inst_id); tip ve değer uyuşmalı |
| M:N ilişkiyi bir tarafa kolon olarak koy | Ayrı tablo şart |
| 1:N’de FK’yı “1” tarafına koy | N tarafına; yoksa bir hücreye çok değer gerekir |
| Çok değerli phone’u virgülle tek kolona yaz | Atomiklik bozulur; ayrı tablo |
| Zayıf varlığın PK’sı sadece discriminator | Sahip PK + discriminator |
| 1:1’de FK yeter | FK + UNIQUE; yoksa 1:N olur |
Kendini test et
Sınavdaki gibi İngilizce sorular. Önce kâğıt kalemle çöz, sonra cevabı aç.
What are the degree and the cardinality of the student relation in the sample database?
Cevabı göster
Derece (degree) = öznitelik sayısı: stu_id, name, dept_name, tot_cred → 4. Kardinalite = satır (tuple) sayısı: S1'den S7'ye → 7. İkisini karıştırma: derece şemaya, kardinalite örneğe (instance) bağlı.
In student(stu_id, name, dept_name, tot_cred), stu_id is the primary key. Is {stu_id, name} a superkey? Is it a candidate key?
Cevabı göster
stu_id zaten her satırı tekil belirliyor; yanına ne eklersen ekle hâlâ tekil: süper anahtar. Aday anahtar ise minimal olmalı. name'i çıkarınca kalan {stu_id} hâlâ anahtar, demek ki {stu_id, name} minimal değil.
In the current student instance no two students have the same name. Can we declare name a candidate key?
Cevabı göster
Anahtar şemanın bir kısıtıdır ve gelecekteki tüm geçerli örnekler için doğru olmalı. Yarın ikinci bir "Ada" kaydolabilir. Doğrulamada name bu örnekte tekrarsız çıktı, ama bu tesadüf. Örnek veri ancak bir şeyin anahtar olmadığını gösterebilir (dept_name tekrarlı, o yüzden anahtar olamaz).
What is the primary key of takes(stu_id, course_id, grade)? Explain why neither attribute alone works.
Cevabı göster
stu_id tekrarlı (S1 dört satırda), course_id tekrarlı (CS101 dört satırda). Çift (stu_id, course_id) örnekte tekrarsız ve iş kuralı da "bir öğrenci bir dersi bir kez alır". grade eklemek gereksiz, (stu_id, grade) ise tekrarlı (S1 iki tane A almış).
A relation R(A, B, C, D) has exactly two candidate keys: {A} and {B, C}. How many superkeys does R have?
Cevabı göster
A'yı içeren alt kümeler: geri kalan B, C, D serbest → 2^3 = 8. {B,C}'yi içerenler: A ve D serbest → 2^2 = 4. İkisini birden içerenler ({A,B,C} ve {A,B,C,D}) iki kez sayıldı → 2. İçerme-dışarma: 8 + 4 − 2 = 10.
With foreign keys enforced, which statement is rejected?
- INSERT INTO student VALUES ('S8','Hakan',NULL,0)
- INSERT INTO takes VALUES ('S9','CS101','A')
- INSERT INTO takes VALUES ('S6','BI100',NULL)
- UPDATE student SET tot_cred = 20 WHERE stu_id = 'S7'
Cevabı göster
takes.stu_id, student.stu_id'ye başvuruyor (foreign key). S9 adında öğrenci yok: referans bütünlüğü ihlali. dept_name'i NULL olan öğrenci eklemek serbest, çünkü FK değeri NULL olabilir. S6 ve BI100 ikisi de var. tot_cred anahtar değil.
What happens to DELETE FROM department WHERE dept_name = 'CS'; if foreign keys are enforced with the default action?
Cevabı göster
Varsayılan davranış (NO ACTION / RESTRICT) başvurulan satırın silinmesine izin vermez. CS'ye I1, I2 (instructor), S1, S2, S5 (student) ve CS101, CS201, CS305 (course) başvuruyor. Silmek istersen önce onları silmeli ya da FK'yı ON DELETE CASCADE / SET NULL ile tanımlamalısın.
Map the M:N relationship takes between student(stu_id, ...) and course(course_id, ...) with relationship attribute grade to a relation schema. Give the primary key and the foreign keys.
Cevabı göster
M:N ilişki her zaman ayrı tablo olur. Kolonlar: iki tarafın birincil anahtarları + ilişkinin öznitelikleri. Birincil anahtar iki tarafın anahtarlarının birleşimi; her biri kendi tablosuna FK.
Map the weak entity set section (discriminator: sec_id, semester, year; attribute room) owned by course(course_id, ...).
Cevabı göster
Zayıf varlığın tablosu sahibin PK'sını FK olarak alır. PK = sahip PK + discriminator. Tanımlayıcı ilişki (sec_course) ayrı tablo olmaz, bilgisi zaten section'daki course_id'de. Sahip silinince şube anlamsız olduğundan FK genelde ON DELETE CASCADE tanımlanır.
An ER design has the strong entities department, instructor (composite name, multivalued phone), student and course; the weak entity section (owner course); the relationships inst_dept (N:1, instructor total), advisor (1:N, instructor to student), takes (M:N between student and section) and dean (1:1 between department and instructor). Fold every 1:N / N:1 relationship into the N side, but keep dean as its own table. How many tables do you get?
Cevabı göster
Varlıklar: department, instructor, student, course, section → 5. Çok değerli phone → inst_phone → 6. takes M:N → 7. dean ayrı tablo → 8. inst_dept, instructor'a dept_name NOT NULL kolonu olarak girer (total katılım NOT NULL demek). advisor, student'a advisor_id kolonu olur. sec_course, section'daki course_id ile temsil edilir. Bileşik name kolonlara bölünür (first_name, last_name), tablo eklemez. Şema SQLite'ta kurulup 8 tablo sayıldı.
In the design above, dean is a 1:1 relationship between department and instructor stored as dean(dept_name, inst_id). Which constraints make it truly 1:1?
Cevabı göster
dept_name PK: bir bölümün en çok bir dekanı. inst_id UNIQUE: bir hoca en çok bir bölümün dekanı. Sadece birini koyarsan ilişki 1:N olur. Doğrulamada aynı hocayı ikinci bölüme dekan yapmak UNIQUE yüzünden reddedildi.
person(pid, name) is specialized into student(tot_cred) and employee(salary), and the specialization is total and disjoint. Which mapping uses the fewest tables without NULL columns, and why is it unsafe if the specialization were overlapping?
Cevabı göster
Yöntem 1: person + her alt küme (3 tablo, alt tablolar pid ile üste FK). Yöntem 2: sadece alt kümeler, her biri üst özniteliklerini kopyalar (2 tablo). Yöntem 3: tek tablo + tip kolonu (1 tablo ama ilgisiz kolonlar NULL). Total ve disjoint ise yöntem 2 her kişiyi tam bir tabloda tutar, NULL yok. Overlapping olsaydı hem öğrenci hem çalışan olan kişinin name'i iki tabloda tekrar eder ve tutarsızlaşabilir; partial olsaydı hiçbir alt kümede olmayan kişi hiçbir yerde saklanamazdı.
Doğrulama: Örnek üniversite veritabanı node:sqlite ile kuruldu. Anahtar iddiaları GROUP BY ... HAVING COUNT(*) > 1 ile, FK ihlalleri PRAGMA foreign_keys=ON altında gerçek INSERT/DELETE ile, süper anahtar sayıları JS alt küme sayımıyla, ER eşlemeleri SQLite'ta şema kurulup tablo sayılarak denetlendi (verify/SEN2104/03.mjs, 32 kontrol).