Ders 17 / 18
Görünümler
Adlandırılmış sorgu olarak görünüm tanımı, karmaşıklığı gizleme ve erişimi daraltma işlevleri, güncellenebilirlik koşulları ve görünüm üzerinden yazmanın motora göre değişen davranışı.
İçindekiler
Buraya kadarki deyimlerin hepsi tabloların üzerinde doğrudan çalıştı. Bu dersin konusu araya giren bir katman: sorgunun kendisine ad vermek ve o adı tablo gibi kullanmak.
Bir kütüphane veritabanında aynı sorgu tekrar tekrar yazılır — açık ödünçler, askıdaki üyeler, şube başına kitap sayısı. Sorgu her yazıldığında yeniden düşünülür, her kopyasında ayrı hata yapılabilir ve şema değiştiğinde her kopya ayrı ayrı güncellenmek zorunda kalır. Görünüm (view), bu tekrarı ortadan kaldıran yapıdır.
Görünüm Adlandırılmış Bir Sorgudur
CREATE VIEW deyimi bir sorguya ad verir. Ad kullanıldığında motor, saklanan sorguyu
çalıştırır. Görünüm veri tutmaz; bu yüzden sanal tablo olarak da anılır.
sqlite3 :memory: <<'SQL' .headers on .mode column CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, soyad TEXT NOT NULL, durum TEXT NOT NULL DEFAULT 'etkin'); INSERT INTO uye VALUES (1,'Ayşe','Demir','etkin'),(2,'Mehmet','Kaya','askida'), (3,'Zeynep','Arslan','etkin'); CREATE VIEW etkin_uye AS SELECT uye_id, ad, soyad FROM uye WHERE durum = 'etkin'; SELECT * FROM etkin_uye; UPDATE uye SET durum = 'etkin' WHERE uye_id = 2; SELECT * FROM etkin_uye; SQL
uye_id ad soyad ------ ------ ------ 1 Ayşe Demir 3 Zeynep Arslan uye_id ad soyad ------ ------ ------ 1 Ayşe Demir 2 Mehmet Kaya 3 Zeynep Arslan
Görünümün tanımı arada hiç değişmedi; yalnızca temel tablodaki bir satırın durumu değişti ve görünüm o değişikliği hemen yansıttı. Bu, görünüm ile kopya tablo arasındaki temel farktır: kopya bir andaki durumu dondurur, görünüm sorgunun kendisini saklar.
Görünüm sorgulanırken tablo gibi davranır. WHERE, ORDER BY, birleştirme, hatta başka
bir görünüm içinde kullanım — hepsi geçerlidir. Sorgu yazan için görünüm ile tablo
arasında bir fark yoktur.
Görünümün İki İşi
Görünümler iki ayrı gereksinimi karşılar. Birincisi karmaşıklığı gizlemektir: birden çok tabloyu birleştiren, gruplayan ve toplama işlevleri kullanan bir sorgu bir kez yazılır, sonra tek bir adla anılır.
sqlite3 :memory: <<'SQL' .headers on .mode column CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, soyad TEXT NOT NULL); CREATE TABLE odunc (odunc_id INTEGER PRIMARY KEY, kitap_id INTEGER NOT NULL, uye_id INTEGER NOT NULL, alis_tarihi TEXT NOT NULL, iade_tarihi TEXT); INSERT INTO uye VALUES (1,'Ayşe','Demir'),(2,'Mehmet','Kaya'),(3,'Zeynep','Arslan'); 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), (9,7,1,'2025-05-14',NULL); CREATE VIEW uye_ozeti AS SELECT u.uye_id, u.ad, u.soyad, count(o.odunc_id) AS toplam_odunc, sum(CASE WHEN o.odunc_id IS NOT NULL AND o.iade_tarihi IS NULL THEN 1 ELSE 0 END) AS acik_odunc FROM uye AS u LEFT JOIN odunc AS o ON o.uye_id = u.uye_id GROUP BY u.uye_id, u.ad, u.soyad; SELECT * FROM uye_ozeti ORDER BY uye_id; SELECT ad, soyad FROM uye_ozeti WHERE acik_odunc > 0 ORDER BY uye_id; SQL
uye_id ad soyad toplam_odunc acik_odunc ------ ------ ------ ------------ ---------- 1 Ayşe Demir 3 1 2 Mehmet Kaya 1 1 3 Zeynep Arslan 0 0 ad soyad ------ ----- Ayşe Demir Mehmet Kaya
İkinci sorgu, bir dış birleştirme ve gruplama yazmak yerine tek bir koşul yazdı.
Görünümün üzerine yazılan WHERE koşulu, saklanan sorgunun sonucuna uygulanır.
Toplama koşulundaki o.odunc_id IS NOT NULL parçası dış birleştirmenin bir sonucudur:
hiç ödüncü olmayan üye için birleştirme boş değerlerle bir satır üretir ve o satır, koşul
yalnızca iade tarihinin boşluğuna baksaydı açık ödünç sayılırdı. Görünüm, bu inceliği bir
kez doğru yazıp saklamanın da yoludur.
Görünümün ikinci işi erişimi daraltmaktır. etkin_uye görünümünü sorgulayan biri, üye
tablosundaki durum sütununu hiç görmez. Sütun ve satır düzeyinde ne gösterileceği
görünümün tanımında belirlenir; okuyucuya temel tablo yerine görünüm verilir. Bu, sonraki
dersin konusu olan yetkilendirmenin en çok kullanılan aracıdır.
Görünüme Yazmak
Görünüm tablo gibi sorgulanabiliyorsa, tablo gibi yazılabilir mi. Bu sorunun yanıtı hem görünümün tanımına hem de motora bağlıdır.
sqlite3 :memory: <<'SQL' .headers on .mode column CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, soyad TEXT NOT NULL, durum TEXT NOT NULL DEFAULT 'etkin'); INSERT INTO uye VALUES (1,'Ayşe','Demir','etkin'),(2,'Mehmet','Kaya','askida'); CREATE VIEW etkin_uye AS SELECT uye_id, ad, soyad FROM uye WHERE durum = 'etkin'; INSERT INTO etkin_uye (uye_id, ad, soyad) VALUES (3,'Zeynep','Arslan'); UPDATE etkin_uye SET soyad = 'Demir Kaya' WHERE uye_id = 1; DELETE FROM etkin_uye WHERE uye_id = 1; SELECT * FROM etkin_uye; SQL
Parse error near line 9: cannot modify etkin_uye because it is a view Parse error near line 10: cannot modify etkin_uye because it is a view Parse error near line 11: cannot modify etkin_uye because it is a view uye_id ad soyad ------ ---- ----- 1 Ayşe Demir
Kullanılan motorda görünümler salt okunurdur; üç yazma denemesi de aynı gerekçeyle reddedildi. Bu, motora göre değişen bir karardır — pek çok motor belirli koşulları sağlayan görünümlere doğrudan yazmaya izin verir.
Standart SQL bu koşulları güncellenebilir görünüm başlığı altında tanımlar. Ortak çekirdeği şudur: görünümün her satırı, temel tablodaki tek bir satıra geri izlenebilmelidir. Bunu bozan yazımlar, görünümü salt okunur yapar:
- Birden çok tablonun birleştirilmesi — bir satır iki tablodan geldiğinde, güncelleme hangisine yazılacağı belirsizdir.
- Gruplama ve toplama işlevleri — sonuçtaki bir satır birden çok temel satırı özetler.
- Tekrarların atılması ve küme işlemleri — satırlar arasındaki karşılık kaybolur.
- Sonuçta ifadeyle üretilen sütunlar — hesaplanmış bir sütuna yazılan değerin girdilere nasıl dağıtılacağı tanımsızdır.
Kalan durum — tek tablodan seçilen, gruplanmamış ve tekrarları atılmamış bir görünüm —
kural olarak güncellenebilirdir. Yukarıdaki etkin_uye bu tanıma uyar ve buna karşın
reddedildi: koşulun sağlanması, motorun desteklediği anlamına gelmez.
Yazılabilir Görünüm Kurmak
Doğrudan yazmayı desteklemeyen motorlarda, yazmanın ne anlama geldiği açıkça tanımlanır. Görünüm üzerine kurulan bir tetikleyici, deyimin yerine geçer ve temel tabloya yazar.
sqlite3 :memory: <<'SQL' .headers on .mode column CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, soyad TEXT NOT NULL, durum TEXT NOT NULL DEFAULT 'etkin'); INSERT INTO uye VALUES (1,'Ayşe','Demir','etkin'),(2,'Mehmet','Kaya','askida'); CREATE VIEW etkin_uye AS SELECT uye_id, ad, soyad FROM uye WHERE durum = 'etkin'; CREATE TRIGGER etkin_uye_ekle INSTEAD OF INSERT ON etkin_uye BEGIN INSERT INTO uye (uye_id, ad, soyad, durum) VALUES (NEW.uye_id, NEW.ad, NEW.soyad, 'etkin'); END; INSERT INTO etkin_uye (uye_id, ad, soyad) VALUES (3,'Zeynep','Arslan'); SELECT * FROM uye; SQL
uye_id ad soyad durum ------ ------ ------ ------ 1 Ayşe Demir etkin 2 Mehmet Kaya askida 3 Zeynep Arslan etkin
INSTEAD OF yazımı, adının söylediğini yapar: ekleme deyimi görünüme uygulanmaz, onun
yerine gövdedeki deyimler çalışır. NEW, eklenmeye çalışılan satırı adlandırır. Görünümde
olmayan durum sütununu tetikleyici doldurdu — görünüme yazmanın anlamı burada
tanımlanmış oldu.
Tetikleyicilerin ayrıntısı, örtük yan etkilerinin yarattığı sorunlar dahil, İleri SQL kursuna aittir. Bu derste gösterilen, görünümü yazılabilir kılmanın standart olmayan yolunun bu olduğudur.
Görünümden Kaybolan Satır
Yazılabilir bir görünümün kendine özgü bir tuzağı vardır. Görünüm satırları bir koşulla süzüyorsa, o koşulu sağlamayan bir satır görünüm üzerinden eklenebilir — ve eklendikten sonra görünümde görünmez.
sqlite3 :memory: <<'SQL' .headers on .mode column CREATE TABLE kitap ( kitap_id INTEGER PRIMARY KEY, baslik TEXT NOT NULL, yazar TEXT NOT NULL, sube_id INTEGER NOT NULL ); INSERT INTO kitap VALUES (1,'Körlük','José Saramago',1); CREATE VIEW merkez_kitap AS SELECT kitap_id, baslik, yazar, sube_id FROM kitap WHERE sube_id = 1; CREATE TRIGGER merkez_kitap_ekle INSTEAD OF INSERT ON merkez_kitap BEGIN INSERT INTO kitap (kitap_id, baslik, yazar, sube_id) VALUES (NEW.kitap_id, NEW.baslik, NEW.yazar, NEW.sube_id); END; INSERT INTO merkez_kitap VALUES (5,'Sessiz Ev','Orhan Pamuk',3); SELECT * FROM merkez_kitap; SELECT * FROM kitap; SQL
kitap_id baslik yazar sube_id -------- ------ ------------- ------- 1 Körlük José Saramago 1 kitap_id baslik yazar sube_id -------- --------- ------------- ------- 1 Körlük José Saramago 1 5 Sessiz Ev Orhan Pamuk 3
Ekleme başarılı oldu, satır temel tabloya yazıldı — ama merkez şubenin kitaplarını gösteren görünümde yok. Görünümü kullanan biri, az önce eklediği satırı bir daha göremez.
Standart SQL bu durum için görünüm tanımına eklenen bir seçenek tanımlar: görünüm üzerinden yazılan satır, görünümün koşulunu sağlamak zorunda tutulur. Bu seçenek de evrensel değildir.
sqlite3 :memory: <<'SQL' CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, durum TEXT NOT NULL); CREATE VIEW etkin_uye AS SELECT uye_id FROM uye WHERE durum = 'etkin' WITH CHECK OPTION; SQL
Parse error near line 2: near "WITH": syntax error
e AS SELECT uye_id FROM uye WHERE durum = 'etkin' WITH CHECK OPTION;
error here ---^
Standartta yazan bir cümle, kullanılan motorda ayrıştırılamadı bile. Bu davranışın motora göre değiştiğini bilmek, taşınabilir şema yazmanın gereğidir: görünüm koşulunun korunması gerekiyorsa ve motor bu seçeneği tanımıyorsa, denetim tetikleyicinin gövdesinde elle yazılır.
Özet
- Görünüm veri tutmaz, sorguyu saklar; temel tablodaki her değişikliği anında yansıtır ve sorgulanırken tablo gibi davranır.
- Görünümün iki işi vardır: birleştirme ve gruplama karmaşıklığını tek adın arkasına almak, ve okuyucuya temel tablonun yalnızca bir bölümünü göstermek.
- Bir görünümün güncellenebilir olması için her satırının tek bir temel satıra geri izlenebilmesi gerekir; birleştirme, gruplama, tekrar atma ve hesaplanmış sütun bunu bozar.
- Koşulları sağlayan bir görünümün yazılabilir olması motora bağlıdır; desteklenmediği
yerde yazmanın anlamı
INSTEAD OFtetikleyicisiyle açıkça tanımlanır. - Süzen bir görünüme koşulu sağlamayan satır yazılabilir ve o satır görünümde görünmez; standardın bunu engelleyen seçeneği her motorda bulunmaz.
Sonraki Adım
Görünümün ikinci işi — okuyucuya temel tablo yerine daraltılmış bir pencere vermek — yarım kalmış bir düşüncedir: görünüm sunulsa bile, temel tablonun kendisi hâlâ ortadadır. Onu kimin görebileceğini söyleyen ayrı bir mekanizma gerekir. Kursun son dersi nesne düzeyi izinleri ele alır: yetkinin kime, hangi nesne üzerinde, hangi işlem için verildiği; bu yetkinin geri alınması; ve verilen izinlerin işin gerektirdiğinden fazla olup olmadığının sayılması.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.