SQL kullanıcı tanımlı fonksiyon yazma: CREATE FUNCTION ve stored procedure farkı
Beceri rehberi

SQL kullanıcı tanımlı fonksiyon yazma: CREATE FUNCTION ve stored procedure farkı

Hazırlayan: Mindset Institute EditörlüğüGüncellendi: 5 dk okuma

Tek değer ya da tablo döndüren fonksiyonu CREATE FUNCTION ile yazmayı, sorguda nasıl çağıracağınızı, hangi kısıtların geçerli olduğunu ve fonksiyon ile stored procedure arasında nasıl seçim yapacağınızı öğrenirsiniz.

Bir bakışta

  1. Fonksiyon parametre alır ve bir değer ya da tablo döndürür; sorgunun içinde ifade gibi kullanılır. Stored procedure ise ayrıca çağrılan ve veri değiştirebilen bir yordamdır.
  2. Fonksiyon türleri skaler, satır içi tablo döndüren ve çok ifadeli tablo döndüren olarak ayrılır. Skaler tek değer, diğerleri tablo döndürür; seçim performansı etkiler.
  3. Fonksiyon veritabanı durumunu değiştirmez. Tabloya yazma, geçici tablo ve dinamik SQL gibi yan etkili işler fonksiyonda yapılamaz.
  4. Satır içi tablo döndüren fonksiyon genellikle en verimli seçimdir. Çok ifadeli tablo fonksiyonu ise birleştirmelerde zayıf sorgu planlarına yol açabilir.
  5. Satır başına çağrılan fonksiyon maliyet doğurur. Büyük tablolarda fonksiyonu önce küçük bir veri kümesiyle sınamak gerekir.

Kullanıcı tanımlı fonksiyon nedir?

Kullanıcı tanımlı fonksiyon, parametre alan, bir işlem yapan ve sonucunu değer ya da tablo olarak döndüren, yeniden kullanılabilir bir veritabanı nesnesidir. Microsoft'un SQL Server belgesi bunu şöyle tarif eder: fonksiyon parametreleri kabul eder, karmaşık bir hesaplama gibi bir işlem yapar ve sonucu döndürür; dönen değer skaler yani tek bir değer ya da bir tablo olabilir.

Fonksiyonun asıl avantajı tekrarı azaltmasıdır. Bir müşteri segmenti kuralı, bir tarih biçimi ya da bir metin temizleme mantığı birçok sorguda tekrar ediyorsa, bunu tek bir yerde tanımlayıp her sorguda çağırırsınız. Kural değiştiğinde tek noktadan güncellenir.

Sözdizimi ürüne göre değişir. Aşağıdaki örnekler SQL Server'ın Transact-SQL diline göredir; PostgreSQL, MySQL ve Oracle fonksiyon tanımında farklı yapılar kullanır. Kavramsal ayrım (fonksiyon sorgunun içinde ifade, prosedür ayrı bir komut) ise tüm sistemlerde geçerlidir.

Tanım yapmak için veritabanında fonksiyon oluşturma yetkisi ve fonksiyonun yazılacağı şema üzerinde değiştirme yetkisi gerekir. Mevcut bir fonksiyonu değiştirmek için CREATE OR ALTER FUNCTION kullanılabilir; yoksa oluşturur, varsa günceller.

Fonksiyon ile stored procedure arasındaki fark

İkisi de yeniden kullanılabilir veritabanı kodudur ama kullanım yerleri farklıdır. Fonksiyon sorgunun içinde, bir ifade ya da tablo gibi kullanılır: SELECT listesinde, WHERE koşulunda, FROM bölümünde. Stored procedure ise ayrı bir komutla çalıştırılır, kendi başına bir iş yapar.

Microsoft belgesinde stored procedure; giriş parametreleri alan, çıkış parametreleriyle birden çok değer döndürebilen, veritabanında işlem yapan ifadeler içeren ve çağıran programa başarı ya da hata durumunu bildiren bir yapı olarak anlatılır. Fonksiyonlarda ise veritabanı durumunu değiştiren işlem yapılamaz, birden çok sonuç kümesi döndürülemez ve hata yönetimi sınırlıdır; TRY...CATCH kullanılamaz.

Basit bir seçim kuralı: sonucu bir sorgunun içine yerleştirmek istiyorsanız fonksiyon, bir işi baştan sona yürütmek, veri yazmak, transaction yönetmek ya da birden çok sonuç üretmek istiyorsanız stored procedure kullanılır.

Şekil 1

Fonksiyon sorgunun içinde, prosedür ayrı komutla çalışır

Fonksiyon ve stored procedure

FonksiyonStored procedure
Nasıl çağrılırSELECT, WHERE, FROM içinde ifade gibiEXECUTE ile ayrı komut olarak
Dönen sonuçBir değer ya da bir tabloÇıkış parametreleri, durum değeri, sonuç kümeleri
Veri değiştirmeVeritabanı durumunu değiştiremezINSERT, UPDATE, DELETE yapabilir
Hata yönetimiTRY...CATCH desteklenmezTRY...CATCH kullanılabilir
Tipik kullanımHesaplama, dönüştürme, parametreli sorguİş akışı, toplu işlem, transaction
Kaynak: sayfa içeriğiMindset Institute

Skaler fonksiyon yazmak

Skaler fonksiyon tek bir değer döndürür. Yapı şöyledir: fonksiyon adı, parametre listesi, dönüş türü ve gövde. Örneğin sipariş tutarına göre segment etiketi üreten bir fonksiyon:

CREATE FUNCTION dbo.SegmentBul (@tutar MONEY, @esik MONEY) RETURNS NVARCHAR(MAX) AS BEGIN RETURN CASE WHEN @tutar >= @esik THEN N'Yüksek' ELSE N'Standart' END; END;

Çağırırken şema adıyla birlikte yazılır: SELECT SiparisId, dbo.SegmentBul(Tutar, @esikDegeri) AS Segment FROM dbo.Siparis. Microsoft belgesi, skaler fonksiyonların en az iki parçalı adla, yani şema ve fonksiyon adıyla çağrılması gerektiğini söyler.

Parametrelerin bir varsayılan değeri varsa, fonksiyon çağrılırken bu değeri almak için DEFAULT anahtar sözcüğü açıkça yazılmalıdır. Bu davranış, parametreyi atlamanın varsayılanı otomatik kullandığı stored procedure'lardan farklıdır; ilk kez fonksiyon yazanların sık takıldığı bir noktadır.

Skaler fonksiyon her satır için çağrılabileceğinden, çok satırlı tablolarda yavaşlık yaratabilir. Basit bir ifadeyle çözülebilen mantık için CASE doğrudan sorguya yazılır; fonksiyon, mantık gerçekten tekrar ediyorsa ve tek yerde tutulması isteniyorsa tercih edilir.

Tablo döndüren fonksiyonlar

Tablo değerli fonksiyonlar bir tablo döndürür ve sorgunun FROM bölümünde, tablo gibi kullanılır. İki türü vardır.

Satır içi tablo değerli fonksiyon tek bir SELECT ifadesinden oluşur. Örnek:

CREATE FUNCTION dbo.MusteriSiparisleri (@musteriId INT) RETURNS TABLE AS RETURN (SELECT SiparisId, Tutar FROM dbo.Siparis WHERE MusteriId = @musteriId);

Çağrısı: SELECT * FROM dbo.MusteriSiparisleri(@id). Bu tür, parametreli bir görünüm gibi davranır ve sorgu iyileştiricisi içeriğini ana sorguyla birlikte optimize edebilir.

Çok ifadeli tablo değerli fonksiyon ise bir tablo değişkeni tanımlar, gövdede birden çok ifadeyle bu değişkeni doldurur ve sonunda döndürür. Karmaşık mantık için esnektir ama Microsoft belgesi, bir çok ifadeli tablo fonksiyonuyla birleştirme yapmanın performans sorunu yaratabileceğini belirtir; çünkü SQL Server bazı ifadelerde tüm iyileştirme tekniklerini kullanamaz. Mümkün olduğunda temel tablolar arasında doğrudan birleştirme tercih edilmelidir.

Şekil 2

Mümkünse satır içi tablo fonksiyonu seçilir

Fonksiyon türü seçimi

Fonksiyon ne döndürecek?
  1. Tek bir değerSkaler fonksiyonÇok satırlı tablolarda satır başına çağrılacağını hesaba katın.
  2. Tek SELECT ile ifade edilebilen tabloSatır içi tablo fonksiyonuParametreli görünüm gibi çalışır, iyileştiriciye açıktır.
  3. Birden çok adım gerektiren tabloÇok ifadeli tablo fonksiyonuSon çare; birleştirmelerde performansı izleyin.
Kaynak: sayfa içeriğiMindset Institute

Fonksiyonun kısıtları

Fonksiyonlar bilinçli olarak sınırlıdır; çünkü sorgunun içinde çalıştıkları için güvenli ve öngörülebilir olmaları gerekir. Microsoft belgesindeki başlıca kısıtlar şunlardır: • Veritabanı durumunu değiştiren işlem yapılamaz • Birden çok sonuç kümesi döndürülemez • TRY...CATCH, @@ERROR ve RAISERROR desteklenmez • Stored procedure çağrılamaz, genişletilmiş saklı yordam çağrısı mümkündür • Dinamik SQL ve geçici tablo kullanılamaz, tablo değişkenleri kullanılabilir • SET ifadeleri, örneğin SET NOCOUNT ON, yazılamaz • Bazı belirsiz sonuçlu yerleşik işlevler, örneğin NEWID ve RAND, doğrudan kullanılamaz

Bu kısıtlar çoğu zaman bir tasarım işareti verir: yapmak istediğiniz iş fonksiyon sınırlarının dışına çıkıyorsa, muhtemelen stored procedure gerekir.

En iyi uygulama olarak belge, fonksiyonu WITH SCHEMABINDING seçeneğiyle oluşturmayı önerir. Böylece fonksiyonun başvurduğu nesneler, fonksiyon da değiştirilmeden değiştirilemez ve beklenmedik sonuçlar önlenir. Fonksiyon veri erişmiyorsa SCHEMABINDING, gereksiz yürütme planı operatörlerini de önleyebilir.

Örnek senaryo ve sık yapılan hatalar

Bir analitik ekip, müşterileri toplam harcamaya göre segmentlere ayırıyor ve bu kural birçok raporda kullanılıyor. Kural ilk başta her sorguya CASE olarak kopyalanmış; bir değişiklik geldiğinde bazı raporlar güncellenmiş, bazıları unutulmuş. Çözüm, segment kuralını bir fonksiyona taşımaktır. Eşik değerleri parametre olarak alınır, çağrılan tek bir yer vardır ve bir sonraki değişiklik tek noktada yapılır. Çok satırlı raporlarda fonksiyon performansı önce küçük bir veri kümesinde denenir.

Sık yapılan hatalar şunlardır: • Veri yazan bir iş mantığını fonksiyona sığdırmaya çalışmak • Büyük tabloda satır başına çağrılan skaler fonksiyonun maliyetini ölçmemek • Çok ifadeli tablo fonksiyonunu büyük birleştirmelerde kullanmak • SCHEMABINDING kullanmayıp alttaki tablo değiştiğinde fonksiyonu bozmak • Fonksiyonu çağırırken şema adını unutmak • Parametre varsayılanını DEFAULT yazmadan kullanmaya çalışmak • Aynı mantığı hem fonksiyonda hem sorguda tutup tutarsızlık yaratmak

Bir kuralı fonksiyon yapıp yapmama kararı, tekrar edip etmediğine, sorgu içinde ifade olarak kullanılmak isteyip istenmediğine ve performans etkisine bakılarak verilir. Çok basit ve bir yerde kullanılan ifadeler için fonksiyon gereksiz karmaşıklık getirir.

SQL fonksiyon becerisini Mindset programlarında nerede çalışırsınız?

SQL ile Programlama Eğitimi sorgular, hesaplamalar, birleştirmeler, toplama ve gruplama ile görüntüleme konularını bir arada işler. Fonksiyon yazımı, bu temellerin üzerine kurulan, sorgularını yeniden kullanılabilir hale getirmek isteyen analist ve geliştiriciler için doğal bir sonraki adımdır.

İlgili Mindset programı

SQL ile Programlama Eğitimi

Sık sorulanlar

Sık sorulan sorular

SQL'de fonksiyon ile stored procedure aynı şey mi?

Hayır. Fonksiyon bir değer ya da tablo döndürür ve sorgunun içinde kullanılır; veritabanı durumunu değiştiremez. Stored procedure ayrı komutla çalıştırılır, veri değiştirebilir, çıkış parametreleri ve durum değeri döndürebilir. Hesaplama ve dönüştürme için fonksiyon, iş akışı ve veri değişikliği için prosedür tercih edilir.

Fonksiyon içinde INSERT ya da UPDATE yapılabilir mi?

Veritabanı tablolarında yapılamaz. Microsoft belgesine göre kullanıcı tanımlı fonksiyonlar veritabanı durumunu değiştiren işlem yapamaz. Yalnız fonksiyon içindeki yerel tablo değişkenleri üzerinde ekleme, güncelleme ve silme yapılabilir. Kalıcı tabloya yazmak gerekiyorsa stored procedure kullanılır.

Satır içi ve çok ifadeli tablo fonksiyonu arasında hangisini seçmeliyim?

Mantık tek bir SELECT ile ifade edilebiliyorsa satır içi tablo fonksiyonu seçilir; sorgu iyileştiricisi bunun içeriğini ana sorguyla birlikte değerlendirebilir. Çok ifadeli fonksiyonlar gerçekten birden çok adım gerektiğinde kullanılır; birleştirmelerde performans sorunu çıkarabilir, bu yüzden dikkatle ölçülmelidir.

Fonksiyonu çağırırken neden şema adı gerekir?

SQL Server'da skaler fonksiyonlar en az iki parçalı adla, yani şema ve fonksiyon adıyla çağrılmalıdır. Bu, nesnenin açıkça tanımlanmasını sağlar. Genellikle dbo şeması kullanılır, ancak kendi şemanıza fonksiyon yazdıysanız o şema adı belirtilir. Şema adını atlamak hata verir.

SCHEMABINDING ne işe yarar?

Fonksiyonun başvurduğu tablo ya da görünüm gibi nesneleri fonksiyona bağlar. Bağlı nesneler, fonksiyon da değiştirilmedikçe değiştirilemez; böylece alttaki yapı değişince fonksiyonun sessizce bozulması önlenir. Microsoft belgesi bunu en iyi uygulama olarak önerir.

SQL Kullanıcı Tanımlı Fonksiyon (CREATE FUNCTION)