Ç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;
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.
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;
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.