Ana SayfaBlog › Veritabanı

SQL Server

SQL Server'da Table-Valued Function Yazımı

Inline ve Multi-Statement TVF arasındaki farklar, yazım kalıpları ve sorgu optimizasyonu için pratik rehber.

📅 6 Haziran 2025 ⏱ ~2 dk okuma 👤 SQL sorgusuyla çalışan herkes

SQL Server'da tekrar eden SELECT sorgularını her yere kopyalamak yerine bir Table-Valued Function (TVF) içine almanız, hem bakım maliyetini hem hata riskini önemli ölçüde düşürür. Bu makalede iki TVF türünü — Inline ve Multi-Statement — somut örneklerle karşılaştırıyor, hangi senaryoda hangisini tercih etmeniz gerektiğini açıklıyoruz.

İçindekiler

  1. 01TVF Nedir, Neden Kullanılır?
  2. 02İki TVF Türü: Inline vs Multi-Statement
  3. 03Inline TVF Yazımı ve Sözdizimi
  4. 04Multi-Statement TVF Yazımı ve Sözdizimi
  5. 05TVF'leri Sorguda Kullanmak
  6. 06Performans: Hangisi Daha Hızlı?
  7. 07Değiştirme ve Silme
  8. 08Sık Yapılan Hatalar
  9. 09Özet Karşılaştırma Tablosu
  10. 10Sonuç

1. TVF Nedir, Neden Kullanılır?

Table-Valued Function, geriye tek bir değer yerine bir sonuç tablosu döndüren kullanıcı tanımlı fonksiyondur. Scalar fonksiyondan farkı tam da bu noktada: FROM veya JOIN içinde, sanki gerçek bir tablo gibi kullanabilirsiniz.

💡Ne Zaman TVF?SELECT sorgularını uygulama koduna gömmek, sorguda değişiklik yapıldığında yeniden derlemeyi zorunlu kılar. TVF ile sorgu mantığı veritabanında kalır; uygulama kodu sadece fonksiyon adını çağırır.

TVF'lerin temel avantajları:

  1. Sorgu mantığı tek yerden yönetilir, tekrar kullanılır.
  2. Parametre alarak dinamik filtreler uygulanabilir (View'ın yapamayacağı şey).
  3. Diğer tablolarla JOIN içinde birleştirilebilir.
  4. Sorguda kolon seçimi yapılabilir: SELECT id, ad FROM dbo.fn_Cari(1)

2. İki TVF Türü: Inline vs Multi-Statement

Özellik Inline TVF (iTVF) Multi-Statement TVF (MSTVF)
GövdeTek RETURN (SELECT ...)BEGIN...END bloğu, birden fazla deyim
Dönüş tanımıRETURNS TABLERETURNS @tablo TABLE (...)
PerformansOptimizer satır içi genişletir → hızlıTablo değişkeni doldurur → daha yavaş
EsneklikTek SELECT yeterliDöngü, koşullu mantık, çoklu INSERT
Ne zaman tercihBasit filtreler, JOIN'e giren sorgularKarmaşık iş mantığı, çok adımlı hesaplamalar

3. Inline TVF Yazımı ve Sözdizimi

Inline TVF'nin gövdesi yalnızca bir RETURN (SELECT ...) ifadesinden oluşur. AS BEGIN...END bloğu yoktur; bu sayede SQL Server sorgu iyileştirici fonksiyonu satır içi genişletir (inline expansion) ve onu bağımsız bir view gibi optimize edebilir.

-- Inline Table-Valued Function örneği
-- Belirli bir müşterinin siparişlerini döndürür
CREATE FUNCTION dbo.fn_MusteriSiparisler
(
@MusteriID INT
)
RETURNS TABLE
AS
RETURN
(
SELECT
s.SiparisID,
s.Tarih,
s.ToplamTutar,
m.Ad + ' ' + m.Soyad AS MusteriAdi
FROM Siparisler s
JOIN Musteriler m ON m.MusteriID = s.MusteriID
WHERE s.MusteriID = @MusteriID
);

En İyi PratikMümkün olduğunca Inline TVF tercih edin. SQL Server query optimizer, iTVF içindeki istatistikleri doğrudan görebildiğinden çok daha etkili bir yürütme planı üretir.

4. Multi-Statement TVF Yazımı ve Sözdizimi

Birden fazla sorgu adımı, döngü ya da koşullu mantık gerektiğinde Multi-Statement TVF kullanılır. Dönüş tipi olarak RETURNS @degisken TABLE (kolon1 tip, ...) şeklinde bir tablo değişkeni tanımlanır; BEGIN...END bloğunun sonunda RETURN yazılarak bu değişken döndürülür.

-- Multi-Statement TVF örneği
-- Müşterinin siparişlerini + toplam özet satırını döndürür
CREATE FUNCTION dbo.fn_SiparisOzet
(
@MusteriID INT
)
RETURNS @Sonuc TABLE
(
SiparisID INT,
Tarih DATE,
Tutar DECIMAL(10,2),
SatirTipi VARCHAR(10)
)
AS
BEGIN
-- Detay satırları ekle
INSERT INTO @Sonuc
SELECT SiparisID, Tarih, ToplamTutar, 'Detay'
FROM Siparisler
WHERE MusteriID = @MusteriID;

-- Özet / toplam satırı ekle
INSERT INTO @Sonuc
SELECT 0, GETDATE(), SUM(ToplamTutar), 'Toplam'
FROM Siparisler
WHERE MusteriID = @MusteriID;

RETURN;
END;

5. TVF'leri Sorguda Kullanmak

Her iki türü de FROM içinde doğrudan ya da başka tablolarla JOIN ederek kullanabilirsiniz:

-- Doğrudan çağırma
SELECT *
FROM dbo.fn_MusteriSiparisler(42);

-- JOIN ile kullanım
SELECT
f.SiparisID,
f.MusteriAdi,
a.Sehir
FROM dbo.fn_MusteriSiparisler(42) f
INNER JOIN Adresler a ON a.MusteriID = 42;

-- CROSS APPLY: her müşteri için ayrı ayrı çağır
SELECT m.Ad, s.SiparisID, s.ToplamTutar
FROM Musteriler m
CROSS APPLY dbo.fn_MusteriSiparisler(m.MusteriID) s;

🔗CROSS APPLY ile güçCROSS APPLY, her satır için TVF'yi ayrı parametre ile çalıştırır. Korelasyonlu alt sorgulara göre çok daha okunabilir ve genellikle daha hızlıdır.

6. Performans: Hangisi Daha Hızlı?

Inline TVF, query optimizer tarafından sanki inline bir view gibi ele alınır: fonksiyon gövdesi çağrıyı yapan sorgunun içine gömülür, istatistikler kullanılır, indeksler devreye girer. Multi-Statement TVF ise önce tablo değişkenini doldurur; bu değişkende istatistik olmadığından optimizer tahmin yapamaz ve genellikle daha kötü bir plan seçer.

⚠️Büyük Veri Setlerinde DikkatMulti-Statement TVF, büyük veri setlerinde belirgin yavaşlamaya neden olabilir. SQL Server 2019 ve sonrasında INTERLEAVED_EXECUTION özelliği MSTVF'nin tahminlerini iyileştirir, ancak Inline TVF hâlâ birinci tercih olmalıdır.

7. Değiştirme ve Silme

-- Mevcut fonksiyonu değiştir (ALTER)
ALTER FUNCTION dbo.fn_MusteriSiparisler
(
@MusteriID INT
)
RETURNS TABLE
AS
RETURN
(
SELECT SiparisID, Tarih, ToplamTutar
FROM Siparisler
WHERE MusteriID = @MusteriID
AND Iptal = 0
);

-- SQL Server 2016+: varsa sil, yoksa hata verme
DROP FUNCTION IF EXISTS dbo.fn_MusteriSiparisler;

8. Sık Yapılan Hatalar

🚫Şema Öneki Olmadan ÇağırmaSELECT * FROM fn_Cari(1) yerine her zaman dbo.fn_Cari(1) yazın. Şema öneki olmadan SQL Server önce sistem fonksiyonlarını arar ve gereksiz yük yaratır.

  1. TVF içinde INSERT / UPDATE / DELETE kullanamazsınız; yan etki yasaktır.
  2. Multi-Statement TVF'de kolon listesini RETURNS @t TABLE (...) bloğunda eksiksiz tanımlayın.
  3. Inline TVF'ye BEGIN...END koymayın; bu onu otomatik olarak MSTVF'ye çevirir.
  4. TVF içinden başka TVF veya Stored Procedure çağırmak performansı olumsuz etkiler.

9. Özet Karşılaştırma Tablosu

Konu Inline TVF Multi-Statement TVF
SözdizimiRETURNS TABLE … RETURN (SELECT)RETURNS @t TABLE … BEGIN…END
Kolon tanımıSELECT listesinden otomatikManuel, önceden belirtilir
Sorgu sayısıYalnızca 1Sınırsız
İstatistik kullanımı✔ Tam destek✘ Tablo değişkeninde yok
Döngü / koşul✔ (IF, WHILE…)
Tavsiye edilen durumBasit, parametrik filtrelerKarmaşık iş mantığı

10. Sonuç

Table-Valued Function'lar, SQL Server sorgularında kod tekrarını ortadan kaldırmanın en temiz yollarından biridir. Kural basit: ihtiyacınız tek bir SELECT'le karşılanıyorsa Inline TVF yazın ve optimizer'ın işini doğru yapmasına izin verin. Birden fazla adım, döngü ya da farklı mantık dalı gerekiyorsa Multi-Statement TVF'e geçin — ancak bunu bilinçli bir performans tercihi olarak yapın.

Netsis, ERP entegrasyonları veya özel .NET uygulamalarında TVF'leri yoğun biçimde kullanıyorsanız, aşağıdaki makaleler de işinize yarayabilir.

Ecol — SQL Server Makaleleri

Daha Fazla SQL Server İçeriği mi Arıyorsunuz?

Stored Procedure'den indeks yönetimine, sorgu optimizasyonundan ERP entegrasyonuna kadar teknik blog yazılarımıza göz atın.

Blog'a Göz At Bize Ulaşın

Kaynaklar

  1. Microsoft Learn — Create User-defined Functions (Database Engine)
  2. Microsoft Learn — CREATE FUNCTION (Transact-SQL)
  3. SQL Server 2019 Intelligent Query Processing: Interleaved Execution for MSTVFs — Microsoft Docs