KULLANICI TANIMLI FONKSİYONLAR Kullanıcı tanımlı fonksiyonlar SQL2000 ile gelen özelliklerden biridir. Fonksiyonlar tek bir değer veya tablo döndürmek için kullanılır. Fonksiyonları veritabanı programlamada nereye koymak gerektiğini anlamak biraz zor olabilir. Bu nedenle, fonksiyonları view ve stored procedurlerle karşılaştıralım. *Dışarıdan parametre alan bir view tanımlamaz. Bu türden ihtiyaçlar için kullanıcı tanımlı fonksiyonlar kullanılır. *Stored procedure leri bir sorgunun parçası olarak kullanamayız. Bir select ifadesi içinde prosedürler bulunamaz ama kullanıcı tanımlı fonksiyonlar bulunabilir. Kullanıcı tanımı fonksiyonlar, tablo gibi, view gibi sorgulanabilir. *Bir tek select ifadesi ile view oluşturamadığımız durumda, kullanıcı tanımlı fonksiyon kullanılır. * Sql serverda bulunmayan, örneğin replace() gibi fonksiyonları tanımlamak için kullanıcı tanımlı fonk. kullanılır. Fonksiyonlar SQL SERVER 2008 Object Explorer ekranında tanımlamış olduğunuz veri tabanı içerisinde Programmability klasörü içerisindeki Function alt klasöründe bulunur. 1
3 çeşit kullanıcı tanımlı fonksiyon vardır. * Scaler değerli (tek değer veren) fonksiyonlar * Tablo döndüren fonksiyonlar * Çok deyimli tablo döndüren fonksiyonlar Scaler değerli kullanıcı tanımlı fonksiyonlar Scaler değerli fonksiyonlar, bir tek değer döndüren fonksiyonlardır. Örnek getdate() bir scaler fonksiyondur, çünkü tek bir değer yani şu anın tarihi ve saatini döndürür. Bazı durumlarda, buna benzer fonksiyonlara ihtiyaç duyulur. Örneğin, bir müşterinin sepetinde kaç ürünün bulunduğu, kaç sipariş verdiğini döndüren fonksiyonlar tanımlanabilir. Genel ifade: CREATE FUNCTION fonksiyonadi(varsaparametreler) RETURNS geridonustipi SQL deyimleri RETURN geridönüşdeğeri 1,2 gibi ay numarası gireceğiz, Ocak, Şubat gibi ay adını veren bir fonksiyon yazınız. Ay değeri 12 den büyük girilirse Tanımsız yazsın. Çözüm CREATE FUNCTION AyAdi(@ay int) RETURNS varchar(20) RETURN( SELECT case @ay WHEN 1 THEN Ocak WHEN 2 THEN Şubat WHEN 3 THEN Mart WHEN 4 THEN Nisan WHEN 5 THEN Mayıs WHEN 6 THEN Haziran WHEN 7 THEN Temmuz WHEN 8 THEN Ağustos 2
) end WHEN 9 THEN Eylül WHEN 10 THEN Ekim WHEN 11 THEN Kasım WHEN 12 THEN Aralık ELSE Tanımsız Müşteri tablosu(musterino,urunno,miktar) Bir müşteri no girildiğinde, bu müşterinin sepetinde toplam kaç ürün olduğunu bulan, bir kullanıcı tanımlı fonksiyon oluşturunuz ve bu fonksiyonu çalıştırınız. Çözüm: CREATE FUNCTION sepeturunsayi(@mno int) RETURNS float RETURN ( SELECT sum(miktar) FROM Sepet WHERE mno=@mno ) Yukarıdaki fonksiyonu çalıştırmak için aşağıdaki sorguyu yazalım -- 1 nolu müşterinin sepetindeki toplam ürün miktari SELECT dbo.sepeturunsayi(1) Yukarıdaki fonksiyonu kullanarak, sepetinde 10 dan fazla ürün bulunan müşterileri listele. SELECT *, dbo.sepeturunsayi(mno) as urunsayi FROM musteri WHERE dbo.sepeturunsayi(mno) >10 Herhangi bir gruba ait müşteri sayısını veren fonksiyon yazınız. (Grup parametre olacak) Çözüm: CREATE FUNCTION MusteriSayisi (@Grup varchar(10)) RETURNS int 3
RETURN (SELECT count(*) FROM musteri WHERE Grubu=@Grup) Her kayıt, farklı bir müşteridir. Kayıt sayısı bize müşteri sayısını verir. Yukarıdaki kodu çalıştırmak için aşağıdaki sorguyu yazalım. -- A grubundaki müşteri sayısı select dbo.musterisayisi('a') -- B grubundaki müşteri sayısı select dbo.musterisayisi('b') Herhangi bir personelin maaşını veren bir fonksiyon oluşturunuz ve bu fonksiyonu çalıştırınız.parametre sicilno olacak CREATE FUNCTION Maas(@sicilno varchar(10)) returns money RETURN (SELECT MA FROM Personel WHERE SicilNo=@sicilno) Go Çalıştırmak SELECT dbo.maas('2053') Parametre müşteri grubu olacak, eğer grubu parametresi değeri NULL olursa tüm müşteri sayısını, NULL değilse verilen gruptaki müşteri sayısını veren bir fonksiyon oluşturunuz. Çözüm: CREATE FUNCTION fnmusterisayisi (@Grubu varchar(10)) RETURNS int DECLARE @sayi int IF @Grubu IS NULL SELECT @sayi=count(*) FROM musteri 4
ELSE SELECT @sayi=count(*) FROM musteri WHERE Grubu=@Grubu RETURN @sayi -- tüm müşteri sayısı SELECT dbo.fnmusterisayisi (NULL) -- A grubundaki müşteri sayısı SELECT dbo.fnmusterisayisi ( A ) -- C grubundaki müşteri sayısı SELECT dbo.fnmusterisayisi ( C ) 5
TABLO DÖNDÜREN FONKSİYONLAR Bu tip fonksiyonlar viewlere çok benzerler. Bir tek select ifadesi içerir. Bu ifadenin sonucunu gösterir. View den farklı olarak dışarıdan parametre alır. Table-valued Function lar, InLine ve MultiLine olmak üzere ikiye ayrılırlar. IN-LINE Parametre alırlar. Üzerinde insert, update ve delete işlemleri yapılabilir. Geriye döndürdüğü tablo tip(kolon sayısı,boyutu vs) olarak, sorgu içerisinde return edilen tablo ile birebir aynıdır. Genel ifade: CREATE FUNCTION fonksiyonadi (varsaparametreler) RETURNS TABLE RETURN Select ifadesi Tüm müşterileri listeleyen fonksiyon oluşturunuz ve bu fonksiyonu sorgulayınız. CREATE FUNCTION fnmusteri () RETURNS TABLE RETURN select * from musteri Sorgulayalım. SELECT * FROM dbo.fnmusteri() Yukarıdaki fonksiyondan faydalanarak A ve C grubundaki müşterileri ayrı ayrı listeleyiniz. -- fnmusteri fonksiyonundan A ve C grubundaki müşteriler SELECT * FROM fnmusteri() WHERE Grubu= A SELECT * FROM fnmusteri() WHERE Grubu= C 6
Yukarıdaki fonksiyona grubu parametresi tanımlayınız ve A ve C grubundaki müşterileri listeleyiniz. -- fonksiyona parametre tanımlayalım ALTER FUNCTION fnmusteri (@grubu varchar(10)) RETURNS TABLE RETURN select * from musteri where grubu=@grubu -- A grubundaki müşteriler SELECT * FROM fnmusteri('a') -- C grubundaki müşteriler SELECT * FROM fnmusteri('c') MULTI-LINE Returns kısmında TABLE yazmak yerine, manuel olarak tablo oluşturup, sonuçları bu tabloya insert etmeye yarayan fonksiyonlardır. Yukarıdaki aynı örneği multi-line function ile yapalım. Buradaki fark; geri dönecek olan tabloyu manuel olarak set edebilmemizdir. 7
Yukarıda Scalar-Valued fonksiyonlarda oluşturmuş olduğumuz SEPET tablo yapısını kullanarak göndermiş olduğumuz grup adına göre istediğimiz alanları görüntüleyecek fonksiyon aşağıdaki gibidir. create function fngrubu (@grup varchar(5)) RETURNS @TABLO TABLE ( mno int, urunkodu int, miktar int, grubu varchar(5) ) INSERT INTO @TABLO SELECT * FROM siparis WHERE grubu=@grup RETURN Çalıştırılması: SELECT * FROM fngrubu('b') Aldığımız sonuç in-line fonksiyon ile aynı. Ancak orada, sonuç kümesindeki kolon sayısı orijinal tablodaki kolan sayısı ile aynıdır. 8
Eğer istenilen kolonlar alınmak istenirse fonksiyon aşağıdaki gibi değiştirilmelidir. alter function fngrubu (@grup varchar(5)) RETURNS @TABLO TABLE ( mno int, urunkodu int, miktar int ) INSERT INTO @TABLO SELECT mno, urunkodu, miktar FROM siparis WHERE grubu=@grup RETURN Çalıştırılması: SELECT * FROM fngrubu('b') 9