Ana içeriğe geç
Kesit SQL
Orta · T-SQL (SQL Server)

Çok ifadeli tablo işlevi, güncellenebilir view, CHECK OPTION, INSTEAD OF

View üzerinden yazmanın koşulları, filtre dışına çıkan satırı engellemek ve yazılamayan view'i yazılabilir yapmak.

Uygulamada aç, 8 alıştırmayı çözÜcretsiz, hesap gerekmez, kurulum yok.

Bu sayfa dersin okuma sürümüdür. Metin bir kutuyu çalıştırmanı ya da adıma geçmeni söylüyorsa dersi uygulamada aç.

Çok ifadeli tablo işlevi

Satır içi işlev (Fonksiyonlar dersi) tek SELECT'tir ve sorguya açılır. Çok ifadeli işlev bir tablo değişkeni doldurur, birden çok adım içerebilir. Karşılığında iyileştirici içine bakamaz; satır tahmini zayıftır. Tek SELECT'le yazılabiliyorsa satır içi işlev yeğlenir.

CREATE FUNCTION dbo.fn_UrunSeviye (@kategori NVARCHAR(50))
RETURNS @t TABLE (urun INT, fiyat DECIMAL(12, 2), seviye NVARCHAR(10))
AS
BEGIN
  INSERT INTO @t (urun, fiyat, seviye)
  SELECT product_id, price, N'normal' FROM products WHERE category = @kategori;
  UPDATE @t SET seviye = N'yüksek' WHERE fiyat > (SELECT AVG(fiyat) FROM @t);
  RETURN;
END;
GO
SELECT seviye, COUNT(*) AS adet FROM dbo.fn_UrunSeviye(N'Kitap') GROUP BY seviye;
Bu motordaİşlev argümanı sabit ya da değişken olmalı. Gerçek sunucuda CROSS APPLY dbo.fn(sutun) de çalışır, burada çalışmaz. İşlev içinde yan etki yasağının tamamı denetlenmez; yalnız istemciye SELECT döndürmek reddedilir.

View üzerinden yazmak

Learn'e göre koşullar: değişiklik tek taban tablonun sütunlarına dokunmalı; sütunlar doğrudan olmalı (toplama ya da hesaplama değil); GROUP BY, HAVING, DISTINCT etkilememeli.

CREATE VIEW dbo.v_kitap AS
SELECT product_id, name, price, category, cost FROM products WHERE category = N'Kitap';
GO
UPDATE dbo.v_kitap SET price = price * 1.1 WHERE product_id IN (SELECT TOP (2) product_id FROM dbo.v_kitap ORDER BY product_id);
SELECT @@ROWCOUNT AS guncellenen;

Filtre dışına kaçan satır

View yalnız Kitap gösteriyor ama üzerinden kategori değiştirilebilir ya da başka kategori eklenebilir; satır bir daha görünmez. WITH CHECK OPTION bunu engeller: view üzerinden yapılan değişiklikten sonra satır view'de görünmeye devam etmeli. Doğrudan tabloya yazmayı kapsamaz.

CREATE VIEW dbo.v_kitap2 AS
SELECT product_id, name, price, category, cost FROM products WHERE category = N'Kitap'
WITH CHECK OPTION;
GO
INSERT INTO dbo.v_kitap2 (product_id, name, price, category, cost) VALUES (900, N'Fare', 10, N'Elektronik', 5);

Yazılamayan view: INSTEAD OF

İki tablonun sütununa birden dokunan yazma ve birleştirmeli view'den DELETE gerçek sunucuda Msg 4405 verir; tek tablonun sütununa dokunan UPDATE geçer. INSTEAD OF tetikleyici yazma isteğini yakalar, ne yapılacağına sen karar verirsin. inserted ve deleted burada da vardır.

Bu motordaMotor birleştirmeli view'e hiç doğrudan yazdırmaz, tek tablonun sütununa dokunan UPDATE için de "desteklemiyor" der. Aşağıdaki örnekte iki tabloya birden yazılıyor: gerçek sunucuda da INSTEAD OF gerekir.
CREATE VIEW dbo.v_siparis AS
SELECT o.order_id, o.status, c.city FROM orders o JOIN customers c ON c.customer_id = o.customer_id;
GO
CREATE TRIGGER trg_v_siparis ON dbo.v_siparis INSTEAD OF UPDATE AS
BEGIN
  UPDATE orders SET status = (SELECT status FROM inserted) WHERE order_id = (SELECT order_id FROM inserted);
  UPDATE customers SET city = (SELECT city FROM inserted) WHERE customer_id = (SELECT customer_id FROM orders WHERE order_id = (SELECT order_id FROM inserted));
END;
GO
UPDATE dbo.v_siparis SET status = 'teslim', city = N'Bursa' WHERE order_id = 1;
SELECT o.order_id, o.status, c.city FROM orders o JOIN customers c ON c.customer_id = o.customer_id WHERE o.order_id = 1;
Burada satır satır, sunucuda ifade başınaBu motorda tetikleyici her satır için bir kez çalışır; bu yüzden örnekteki tekil alt sorgu geçer. Gerçek SQL Server'da tetikleyici ifade başına bir kez çalışır ve inserted bütün satırları içerir; çok satırlı güncellemede bu alt sorgu hata verir. Gerçek kodda JOIN inserted yaz. Motor ayrıca INSTEAD OF'u yalnız view üzerinde kabul eder ve gövdede IF gibi akış komutu çalıştırmaz.
Alıştırmalara geç (8)