Ders 02 / 14
İlişkisel Model
Bağıntı, satır, sütun ve alan kavramlarının tanımı; satır sırasının ve satır yinelemesinin modeldeki yeri ile SQL tablosunun bağıntıdan ayrıldığı noktalar.
İçindekiler
Önceki ders, bir metin dosyasındaki satırlar ile veritabanındaki satırlar arasında biçimlendirmeden daha derin bir fark olduğunu söyleyerek bitti. Bu dersin sorusu o farkı adlandırır: bir tablonun altında hangi matematiksel yapı durur, ve bu yapı tabloya bakarken gördüğümüz hangi ayrıntıların veriye ait olmadığını söyler?
Yanıt tek bir kavramda toplanır. İlişkisel modelde veri, tablo gibi görünen ama tablo olmayan bir nesnede tutulur: bağıntı (relation). Bu dersteki her kural, bağıntının küme kuramından gelen tanımının doğrudan sonucudur.
Alan
Bir sütunun alabileceği değerlerin kümesine o sütunun alanı (domain) denir. Şubenin bulunduğu il bir metin alanından, kitabın yayın yılı bir tam sayı alanından, kitabın ödünç verilebilirliği iki elemanlı bir doğruluk alanından değer alır.
Alan, tipten daha dardır. Yayın yılının tipi tam sayıdır; alanı ise “1450 ile 2100 arasındaki tam sayılar” olabilir. Tip, değerin nasıl saklandığını; alan, hangi değerlerin anlamlı olduğunu söyler. Şemada alan, bir kısıt (constraint) olarak yazılır:
sqlite3 :memory: <<'SQL' CREATE TABLE kitap ( isbn TEXT NOT NULL, baslik TEXT NOT NULL, yayin_yili INTEGER NOT NULL CHECK (yayin_yili BETWEEN 1450 AND 2100) ); INSERT INTO kitap VALUES ('978-975-0000-01-1', 'Kayıp Zaman', 2019); INSERT INTO kitap VALUES ('978-975-0000-02-8', 'Deniz Fenerleri', 20199); SQL
Runtime error near line 7: CHECK constraint failed: yayin_yili BETWEEN 1450 AND 2100 (19)
Parmağın kaydığı bir eklemede yıl 20199 olarak yazılmıştır ve motor onu geri çevirir.
Alanı şemada tanımlamamak, bu denetimi veriye yazan her programın ayrı ayrı yapmasını
beklemek demektir.
Bağıntı
tane alan verildiğinde, bunların kartezyen çarpımı her bileşeni ilgili alandan seçilmiş bütün ’li sıralı listelerin kümesidir. Bir bağıntı, bu çarpımın bir alt kümesidir:
Kartezyen çarpım, “yazılabilecek her şey”i verir; bağıntı, bunlardan “gerçekten doğru
olanlar”ı seçer. Şube bağıntısında ('MRK', 'Merkez', 'Ankara') üçlüsü bulunuyorsa, bu
kütüphanede MRK kodlu, Merkez adlı, Ankara’daki bir şubenin var olduğu bildirilmiştir.
Bağıntıda bulunmayan üçlüler ise yanlış sayılır. Bir tablo, bir olgu listesidir.
Bağıntının iki parçası vardır. Başlık (heading), öznitelik adı ile alan eşleşmelerinin kümesidir ve zamanla değişmez. Gövde (body), başlığa uyan satırların kümesidir ve her eklemede, silmede, güncellemede değişir. Başlıktaki öznitelik sayısına bağıntının derecesi (degree), gövdedeki satır sayısına kardinalitesi (cardinality) denir.
Satır ve Sütun
Gövdedeki her eleman bir satır, kuramsal adıyla bir demettir (tuple). Satır,
öznitelik adlarından değerlere giden bir eşlemedir: sube_kodu özniteliğine 'MRK',
ad özniteliğine 'Merkez' karşılık gelir.
Başlıktaki her öğe bir sütundur ve bir özniteliğe (attribute) karşılık gelir.
Sütun bir ada ve bir alana sahiptir; sıra numarasına değil. sube bağıntısında ikinci
sütun diye bir kavram yoktur, ad sütunu vardır.
Buradan iki sonuç doğar ve ikisi de kullanımda sık unutulur.
Satırların Sırası Veriye Ait Değildir
Gövde bir kümedir; kümenin elemanları sıralı değildir. Bir sorgu satırları hangi sırayla verirse versin, o sıra veriden değil, motorun seçtiği erişim yolundan gelir. Aynı tabloya bir dizin eklemek, hiçbir satırı değiştirmeden sonucun sırasını değiştirmeye yeter:
sqlite3 :memory: <<'SQL' .headers on .mode box CREATE TABLE sube (sube_kodu TEXT, ad TEXT, il TEXT); INSERT INTO sube VALUES ('MRK', 'Merkez', 'Ankara'), ('BHC', 'Bahçelievler', 'Ankara'), ('KDK', 'Kadıköy', 'İstanbul'); SELECT sube_kodu, ad FROM sube; CREATE INDEX sube_ad ON sube (ad, sube_kodu); SELECT sube_kodu, ad FROM sube; SQL
┌───────────┬──────────────┐ │ sube_kodu │ ad │ ├───────────┼──────────────┤ │ MRK │ Merkez │ │ BHC │ Bahçelievler │ │ KDK │ Kadıköy │ └───────────┴──────────────┘ ┌───────────┬──────────────┐ │ sube_kodu │ ad │ ├───────────┼──────────────┤ │ BHC │ Bahçelievler │ │ KDK │ Kadıköy │ │ MRK │ Merkez │ └───────────┴──────────────┘
İki sorgu aynıdır, veri aynıdır, sıra farklıdır. İkinci sorgu artık tabloyu değil, ada göre düzenli tutulan dizini okumaktadır. Hangi erişim yolunun seçileceği motora göre değişir; kural olarak sıralı sonuç isteniyorsa sıralama açıkça istenmelidir. Sırayı açıkça istemeyen bir program, doğruluğunu tesadüfe bağlamıştır.
Yinelenen Satırlar ve Çok Küme
Küme kuramında bir eleman ya kümededir ya değildir; iki kez bulunamaz. Bağıntı tanımı gereği yinelenen satır barındırmaz. SQL tablosu ise bu noktada bağıntıdan ayrılır: anahtar tanımlanmamışsa aynı satır iki kez yazılabilir.
sqlite3 :memory: <<'SQL' .headers on .mode box CREATE TABLE sube (sube_kodu TEXT, ad TEXT, il TEXT); INSERT INTO sube VALUES ('MRK', 'Merkez', 'Ankara'); INSERT INTO sube VALUES ('MRK', 'Merkez', 'Ankara'); SELECT COUNT(*) AS satir, COUNT(DISTINCT sube_kodu) AS farkli_kod FROM sube; SQL
┌───────┬────────────┐ │ satir │ farkli_kod │ ├───────┼────────────┤ │ 2 │ 1 │ └───────┴────────────┘
SQL tablosu bir küme değil, bir çok kümedir (multiset): aynı değer birden çok kez bulunabilir. Bu, modelin bir eksiği değil, kuramdan bilinçli bir sapmadır — yinelenenleri elemek sıralama ya da karma gerektirir, yani ücretlidir. Sonuç şudur: tablonun bağıntı gibi davranması kendiliğinden olmaz, şemada istenir. Bunu isteme yolu anahtar tanımlamaktır ve sıradaki dersin konusu budur.
Bağıntı Değişkeni ve Şema
Yukarıdaki sube tablosu, zaman içinde değişen bir değeri tutar: bugün üç satır, yarın
dört. Kuramda bu ayrım adlandırılmıştır. Bağıntı değişkeni (relation variable) bir
addır ve o adın herhangi bir andaki değeri bir bağıntıdır. CREATE TABLE bir bağıntı
değişkeni oluşturur; INSERT onun değerini değiştirir.
Buradan, veritabanı çalışmasının iki ayrı düzlemi çıkar. Şema (schema), bağıntı değişkenlerinin başlıklarını ve üzerlerindeki kısıtları belirtir; nadiren değişir ve değiştiğinde göç gerektirir. Örnek (instance), belirli bir andaki değerler bütünüdür; sürekli değişir. Bir tasarım hatası şemadadır, bir veri hatası örnektedir; ilkini düzeltmek ikincisinden pahalıdır.
Değerin Bölünmezliği
Modelin son kuralı, satır ile sütunun kesiştiği yerde tek bir değer bulunmasıdır.
Şubenin telefon numaraları için '0312-000-0001, 0312-000-0002' biçiminde tek bir metin
yazmak, oraya bir liste sıkıştırmak demektir. Sistem o metni bölünmez sayar: içindeki
ikinci numarayı arayan bir sorgu yazılamaz, bir numaranın kaldırılması metin düzenlemeye
dönüşür, numara üzerinde kısıt tanımlanamaz.
Bunun karşılığı, çok değerli olguyu ayrı bir bağıntıya taşımaktır — her telefon numarası kendi satırında, şube koduyla birlikte. Bu kural Normalizasyon konusunda birinci normal form adıyla biçimselleştirilecek; şimdilik modelin bir gereği olarak durur.
Özet
- Bağıntı, öznitelik alanlarının kartezyen çarpımının bir alt kümesidir; başlığı sabit, gövdesi değişkendir.
- Alan, bir sütunun anlamlı değerler kümesidir ve tipten dardır; şemada kısıt olarak yazılır.
- Gövde bir küme olduğundan satır sırası veriye ait değildir; sıralı sonuç isteniyorsa açıkça istenmelidir.
- SQL tablosu çok küme olduğu için yinelenen satır kabul eder; bağıntı gibi davranması şemada anahtar tanımlanmasına bağlıdır.
- Şema bağıntı değişkenlerini ve kısıtlarını, örnek ise belirli bir andaki değerleri belirtir.
Sonraki Adım
Bu ders iki kez aynı yere çıktı: satırların birbirinden ayırt edilebilmesi gerekiyor, ve bu ayırt etme şemada söylenmedikçe gerçekleşmiyor. Sıradaki ders, bir satırı tek başına belirleyen sütun kümesini tanımlar; birden çok adayın bulunduğu durumda hangisinin seçileceğini tartışır ve bir bağıntının satırlarını başka bir bağıntının satırlarına bağlayan anahtarı kurar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.