Ders 02 / 18
SELECT Yapısı
Sütun listesinin ne olduğu, takma adlar, hesaplanmış ifadeler, yinelenen satırların elenmesi ve yan tümcelerin yazım sırası ile değerlendirme sırası arasındaki fark.
İçindekiler
Önceki ders SQL’in beş deyim ailesini ayırdı ve sorgulama ailesinin tek bir deyimden —
SELECT — oluştuğunu söyledi. Bu deyim örnek olarak bir kez kullanıldı: iki sütun, bir
tablo, bir koşul. Oysa SELECT yan tümcesine yazılabilecek şey tablo sütunlarının
adlarıyla sınırlı değildir.
Bu ders sütun listesinin ne kabul ettiğini kurar. Bir sorgunun ürettiği sonuç yeni bir bağıntıdır; sütunları tablodaki sütunlarla aynı olmak zorunda değildir. Adları değişebilir, sayıları değişebilir, hiç var olmayan bir sütun hesaplanarak eklenebilir.
Aşağıdaki blok kurs boyunca kullanılan şemayı ve örnek veriyi kurar. Bu dersin bütün
sorguları bu blokta oluşturulan kutuphane.db dosyası üzerinde çalışır.
rm -f kutuphane.db sqlite3 kutuphane.db <<'SQL' CREATE TABLE sube (sube_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, sehir TEXT NOT NULL); CREATE TABLE kitap (kitap_id INTEGER PRIMARY KEY, baslik TEXT NOT NULL, yazar TEXT NOT NULL, basim_yili INTEGER, sube_id INTEGER REFERENCES sube(sube_id)); CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, soyad TEXT NOT NULL, eposta TEXT, kayit_tarihi TEXT NOT NULL); CREATE TABLE odunc (odunc_id INTEGER PRIMARY KEY, kitap_id INTEGER NOT NULL REFERENCES kitap(kitap_id), uye_id INTEGER NOT NULL REFERENCES uye(uye_id), alis_tarihi TEXT NOT NULL, iade_tarihi TEXT); INSERT INTO sube VALUES (1,'Merkez','Ankara'),(2,'Bahçelievler','Ankara'), (3,'Kadıköy','İstanbul'),(4,'Konak','İzmir'); INSERT INTO kitap VALUES (1,'Körlük','José Saramago',1995,1),(2,'Tutunamayanlar','Oğuz Atay',1972,1), (3,'Kum Kitabı','Jorge Luis Borges',1975,2),(4,'Yaban','Yakup Kadri',1932,2), (5,'Sessiz Ev','Orhan Pamuk',1983,3),(6,'Anayurt Oteli','Yusuf Atılgan',NULL,3), (7,'Tehlikeli Oyunlar','Oğuz Atay',1973,NULL); INSERT INTO uye VALUES (1,'Ayşe','Demir','[email protected]','2023-02-14'), (2,'Mehmet','Kaya','[email protected]','2023-05-30'),(3,'Zeynep','Arslan',NULL,'2024-01-09'), (4,'Emre','Yıldız','[email protected]','2024-03-22'),(5,'Selin','Aydın',NULL,'2024-11-05'), (6,'Burak','Şahin','[email protected]','2025-01-18'); INSERT INTO odunc VALUES (1,1,1,'2025-01-10','2025-01-24'),(2,2,1,'2025-02-02','2025-02-20'), (3,1,2,'2025-02-11',NULL),(4,3,3,'2025-03-01','2025-03-15'),(5,4,3,'2025-03-18','2025-04-02'), (6,1,4,'2025-04-05','2025-04-19'),(7,5,4,'2025-04-21',NULL),(8,2,5,'2025-05-02','2025-05-30'), (9,7,1,'2025-05-14','2025-05-28'),(10,3,5,'2025-06-03',NULL),(11,6,2,'2025-06-11','2025-06-25'), (12,4,4,'2025-06-20','2025-07-04'); SQL
Yıldız ve Açık Liste
En kısa sorgu, tablonun bütün sütunlarını ister.
sqlite3 kutuphane.db <<'SQL' .headers on .mode column SELECT * FROM sube; SQL
sube_id ad sehir ------- ------------ -------- 1 Merkez Ankara 2 Bahçelievler Ankara 3 Kadıköy İstanbul 4 Konak İzmir
Yıldız, “tablonun o anki bütün sütunları” anlamına gelir. Keşif sırasında yararlıdır ve kalıcı kodda üç ayrı soruna yol açar. Birincisi, şemaya sonradan sütun eklendiğinde sonuç kümesinin sütun sayısı sessizce değişir; sütunları sırayla okuyan çağıran taraf bozulur. İkincisi, gerekmeyen sütunlar da okunur — geniş bir metin sütunu için bu, gereksiz disk ve ağ trafiği demektir. Üçüncüsü, sorguyu okuyan kişi hangi sütunlara gerçekten ihtiyaç duyulduğunu göremez.
Açık liste bu üç sorunu birden ortadan kaldırır.
sqlite3 kutuphane.db <<'SQL' .headers on .mode column SELECT baslik, yazar FROM kitap; SQL
baslik yazar ----------------- ----------------- Körlük José Saramago Tutunamayanlar Oğuz Atay Kum Kitabı Jorge Luis Borges Yaban Yakup Kadri Sessiz Ev Orhan Pamuk Anayurt Oteli Yusuf Atılgan Tehlikeli Oyunlar Oğuz Atay
Sütun listesindeki sıra sonuçtaki sıradır. Tablodaki fiziksel sıra bağlayıcı değildir.
Takma Adlar
Sonuç kümesindeki bir sütunun adı AS ile değiştirilebilir. Buna takma ad (alias)
denir.
sqlite3 kutuphane.db <<'SQL' .headers on .mode column SELECT baslik AS kitap_adi, yazar AS yazan FROM kitap WHERE sube_id = 1; SQL
kitap_adi yazan -------------- ------------- Körlük José Saramago Tutunamayanlar Oğuz Atay
Takma ad iki işe yarar. Sütuna anlamlı bir ad verir — özellikle hesaplanmış ifadelerde, çünkü hesaplanmış bir sütunun öntanımlı adı motora göre değişen bir dizedir. İkincisi, birleştirmelerde aynı adı taşıyan iki sütunu ayırt etmeyi sağlar; bu, ikinci konunun konusudur.
AS sözcüğü çoğu motorda isteğe bağlıdır — baslik kitap_adi yazımı da çalışır. Yine de
AS yazmak, sütun listesinde unutulmuş bir virgülün sessizce takma ada dönüşmesini
önler. SELECT baslik yazar FROM kitap deyimi hata vermez; iki sütun yerine, adı yazar
olan tek bir sütun döndürür.
Hesaplanmış İfadeler
Sütun listesine sütun adı değil, ifade yazılabilir. İfade satır başına değerlendirilir ve sonuç kümesinde yeni bir sütun olarak görünür.
Metin birleştirme standartta || işleciyle yazılır.
sqlite3 kutuphane.db <<'SQL' .headers on .mode column SELECT ad || ' ' || soyad AS tam_ad, kayit_tarihi FROM uye; SQL
tam_ad kayit_tarihi ------------- ------------ Ayşe Demir 2023-02-14 Mehmet Kaya 2023-05-30 Zeynep Arslan 2024-01-09 Emre Yıldız 2024-03-22 Selin Aydın 2024-11-05 Burak Şahin 2025-01-18
Birleştirme işlecinin yazımı motora göre değişir: bazı motorlar || yerine ya da
onunla birlikte bir birleştirme işlevi sunar, bazılarında || bambaşka bir anlam taşır.
Taşınabilir olması gereken sorgularda bu, ilk kontrol edilecek noktalardandır.
Aritmetik ifadeler de aynı biçimde yazılır. Aşağıdaki sorgu basım yılından on yıllık dilimi hesaplar.
sqlite3 kutuphane.db <<'SQL' .headers on .mode column SELECT baslik, basim_yili, (basim_yili / 10) * 10 AS on_yil FROM kitap; SQL
baslik basim_yili on_yil ----------------- ---------- ------ Körlük 1995 1990 Tutunamayanlar 1972 1970 Kum Kitabı 1975 1970 Yaban 1932 1930 Sessiz Ev 1983 1980 Anayurt Oteli Tehlikeli Oyunlar 1973 1970
İki gözlem var. Birincisi, iki tam sayının bölümünün tam sayı olarak mı yoksa ondalık
olarak mı değerlendirileceği motora göre değişir; burada tam sayı bölmesi
uygulandığı için 1995 / 10 işlemi 199 verdi. Taşınabilir yazım, bölmeden önce tipi
açıkça belirlemektir.
İkincisi, Anayurt Oteli satırında on_yil sütunu boş. Basım yılı bilinmediği için
ifadenin sonucu da bilinmiyor: boş değeri içeren aritmetik ifade boş değer üretir. Bu
davranış beşinci dersin tamamını dolduracak kadar sonuç doğurur.
Yinelenen Satırların Elenmesi
SELECT sonucu bir çoklu kümedir: aynı satır birden çok kez görünebilir. DISTINCT
anahtar sözcüğü yinelenen satırları eler.
sqlite3 kutuphane.db <<'SQL' .headers on .mode column SELECT DISTINCT yazar FROM kitap; SQL
yazar ----------------- José Saramago Oğuz Atay Jorge Luis Borges Yakup Kadri Orhan Pamuk Yusuf Atılgan
Yedi kitap var ama altı yazar döndü: aynı yazarın iki kitabı tek satıra indi.
DISTINCT sütuna değil, sonuç satırının tamamına uygulanır. SELECT DISTINCT yazar, baslik
yazımı yazarları değil, yazar–başlık çiftlerini tekilleştirir; kitap başlıkları farklı
olduğu için hiçbir satır elenmez. Bu, DISTINCT ile en sık yapılan yanlıştır: bir sütunu
tekilleştirmek isterken sonuç kümesine ikinci bir sütun eklendiğinde eleme etkisiz kalır.
Çıktıdaki sıraya güvenilmemelidir. Sıralama belirtilmeyen bir sorgunun satır sırası tanımsızdır; motor tekilleştirmeyi hangi yöntemle yaparsa sıra ona göre çıkar. Sıra gerektiğinde dördüncü dersteki sıralama yan tümcesi yazılır.
Değerlendirme Sırası
Yazım sırası SELECT, FROM, WHERE biçimindedir; anlam sırası ise FROM, WHERE,
SELECT biçimindedir. Motor önce hangi tablodan okuyacağını belirler, sonra satırları
süzer, en son sütun listesini hesaplar.
Bunun ölçülebilir bir sonucu var: SELECT yan tümcesinde tanımlanan bir takma ad,
kendisinden önce değerlendirilen WHERE yan tümcesinde standarda göre görünür değildir.
sqlite3 kutuphane.db <<'SQL' .headers on .mode column SELECT ad || ' ' || soyad AS tam_ad FROM uye WHERE tam_ad = 'Ayşe Demir'; SQL
tam_ad ---------- Ayşe Demir
Sorgu burada çalıştı. Ancak bu, standart bir davranış değil, kullanılan motorun
sağladığı bir gevşemedir; aynı sorgu başka bir motorda “böyle bir sütun yok” hatası
verebilir. Davranış motora göre değişir. Taşınabilir yazım, ifadenin WHERE içinde
tekrar edilmesidir:
sqlite3 kutuphane.db <<'SQL' .headers on .mode column SELECT ad || ' ' || soyad AS tam_ad FROM uye WHERE ad || ' ' || soyad = 'Ayşe Demir'; SQL
tam_ad ---------- Ayşe Demir
İfadenin iki kez yazılması motorun onu iki kez hesaplayacağı anlamına gelmez; bildirimsel dilde tekrar, plana değil yazıma aittir.
Özet
- Sonuç kümesi yeni bir bağıntıdır; sütunları tablonun sütunlarıyla aynı olmak zorunda değildir.
- Yıldız yazımı keşif için uygundur, kalıcı sorgularda şema değişikliğine kırılgan ve gereksiz veri okur.
- Takma ad sütuna ad verir;
ASyazmak, unutulmuş virgülün sessizce takma ada dönüşmesini önler. - Sütun listesine ifade yazılabilir; boş değer içeren ifade boş değer üretir.
DISTINCTtek bir sütuna değil, sonuç satırının tamamına uygulanır.- Yazım sırası ile değerlendirme sırası ayrıdır;
SELECTiçindeki takma adınWHEREiçinde görünürlüğü motora göre değişir.
Sonraki Adım
Bu dersteki WHERE yan tümceleri tek bir eşitlikten ibaretti. Oysa süzme, sorgunun
sonucunu en çok belirleyen yan tümcedir: karşılaştırma işleçleri, mantıksal bağlaçlar,
aralık ve liste denetimleri, metin örüntüsü eşleme. Sonraki ders koşul yazımını bütün
biçimleriyle kurar ve örüntü eşlemenin büyük/küçük harf davranışının neden motora bağlı
olduğunu gösterir.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.