30 Nisan 2012 Pazartesi

MS SQL 'de DML Triggers - Instead Of Triggers

Merhaba arkadaşlar.
"After trigger" nesneleri belirtilen işlemden sonra çalışırlardı. Yani belirtilen işlem gerçekleştikten sonra çalışırlardır. Fakat "Instead Of Trigger" nesneleri ise belirtilen işlem komutu gelince tetiklenirler ve o belirtilen işlemi yapmazlar. Onun yerine bizim belirttiğimiz işlemi yaparlar.

Hemen bir örnek ile kullanımını görelim.  Bu örnek için Northwind veri tabanında çalışıyorsanız eğer, "LogFile" adında bir tablo oluşturun. "Id", "SilenKisi" ve "Tarih" adında uc kolonu olması yeterlidir. Daha sonra "UrunKoruma" adında, "Products" tablosunun üzerinde bir "trigger" oluşturalım. Örneğin bir şirkette çalışıyorsunuz ve bir tablodan bir veri silinmeye çalışıldığında; sizden verinin silinmemesi, veriyi silmeye çalışan kişinin "Computer Name" 'i istendi. Tek yapmanız gereken aşağıdaki "trigger" nesnesini oluşturmak.

CREATE TRIGGER UrunKoruma
ON dbo.Products
INSTEAD OF DELETE
AS
      INSERT INTO dbo.LogFile (SilenKisi,Tarih)
      VALUES (SUSER_SNAME() , -- SilenKisi - nvarchar(50)
      GETDATE()               -- Tarih - datetime
      )
      PRINT 'Kac oglum Patron gelio'

"LogFile" tablomuza daha hiç veri girişi yapılmamış. Şimdi oluşturduğumuz "trigger" nesnesini tetiklemeye çalışalım.
DELETE FROM dbo.Products WHERE ProductID=65

Silmeye çalıştım arkadaşlar, bakalım silmiş mi?
SELECT ProductID,ProductName FROM dbo.Products WHERE ProductID=65

Hayır arkadaşlar görüldüğü üzere silmemiş. Birinci beklentimiz de buydu zaten. İkinci beklentimiz de "LogFile" tablosuna kaydetmesiydi, bakalım bir kayıt eklenmiş mi?

SELECT * FROM dbo.LogFile

"Trigger" nesnemiz on numara çalışıyor arkadaşlar."LogFile" tabloma da beklediğim kayıt başarılı bir şekilde gelmiş.

Bir örnek daha yapalım arkadaşlar. "Hesap" adında bir tablo oluşturalım. "Id", "Ad", "Bakiye"(money) ve "SilindiMi"(bit) kolonları olsun. Tablomuza iki kayıt girelim.

Bu tablomdan bir kaydın silinmesi istenirse, silinmesinde "SilindiMi" kolonu "true" yapılsın. Zaten arkadaşlar hiçbir şirkette kolay kolay hiçbir veri silinmez. Ya başka tabloya taşınır, yada bizim yaptığımız gibi bir işlemle silindi olarak işaretlenir. Şimdi gelelim "SilindiIsaretle" adında bir "trigger" yazmaya:

CREATE TRIGGER SilindiIsaretle
ON dbo.Hesap
INSTEAD OF DELETE 
AS
      DECLARE @Id INT
      SELECT @Id= Id FROM DELETED
      UPDATE dbo.Hesap SET SilindiMi=WHERE Id=@Id
      PRINT 'Silmeye kiayamadim :D'

"Trigger" nesnemi tetiklemek için tablodan bir kayıt silmeye çalışalım.
DELETE FROM dbo.Hesap WHERE Id=1

Tablomuza bakalım silinmiş mi yada ne gibi bir değişiklik olmuş?
SELECT * FROM dbo.Hesap  

Amacımıza ulaştık arkadaşlar.

Başka bir yazıda görüşmek dileğiyle, hoşçakalın...

MS SQL 'de DML Triggers Giriş - After (For) Triggers

Merhaba arkadaşlar.
"Strored Procedure" nesnelerim benim için başlı başına bir iş yapabiliyordu. Tanımladıktan sonra kullanmak istediğim yerde çağırıp işimi görebiliyordum. İşte arkadaşlar "Trigger" nesnelerini de tanımlandıktan sonra otomatik çalışan "Strored Procedure" olarak tanımlayabiliriz. Otomatik olarak çalışmaktan kasıt: "Trigger" nesnelerini çalışmasını istediğim zaman çağırmaya gerek yoktur. Belirttiğim olay gerçekleştiğinde, belirttiğim işlemin yapılması söz konusudur.

"Trigger" 'lar birer veri tabanı nesneleridirler. Bu yüzden manipüle edilirken "DDL" (create, alter, drop) dili ile yönetilirler. "Trigger" nesneleri ikiye ayrılırlar: "DML Triggers" ve "DDL Triggers" olmak üzere. "DDL Triggers" nesneleri içerisinde tanımladığımız kodlar, bir veri tabanı nesnesi "create, alter, drop" işlemlerinden istediğimiz işleme uğradığında devreye girer. Bu yazımda da "DML Triggers" nesnelerini inceleyeceğiz.

"DML Triggers" nesneleri oluşturulurken bir tablo üzerinde tanımlanırlar ve bu tabloya yapılan "insert, update, delete" gibi işlemleri gözlerler. Bu davranışları itibariye "c sharp" tarafındaki "event" nesnelerine benzerler. İstediğimiz tablo üzerinde, hangi olaydan sonra veye hangi olay yerine, ne yapılmasını istiyorsak "DML Triggers" nesnelerinin gövdesinde tanımlarız. Tablo bağımlı çalıştığından dolayı, hangi tablo üzerinde tanımlanmışsa "Object Explorer" penceresinde, o tablonun altında yerini alır ve simgesi "şimşek" 'tir.

"DML Triggers" nesneleri de kendi aralarında ikiye ayrılır: "After" (For) ve "Instead Of" olmak üzere. "After" trigger 'lar kendisinden sonra belirttiğimiz işlemden sonra, bizim tanımladığımız işlemleri yapar. "Instead Of" trigger 'lar ise kendisinden sonra belirttiğimiz işlemden yerine, bizim tanımladığımız işlemleri yapar. Öncelikle "After Trigger" nesnelerinin kullanımlarını inceleyelim.

Örneğin "Northwind" veri tabanında bir ürünün siparişi verildiğinde, sipariş edilen miktar kadar o ürünün stoğundan düşsün istiorum. Bu örnekte dikkat edilmesi gereken nokta, bir üründen sipariş verilmesi demek "Order Details" tablosuna kayıt girilmesi demektir. Bu yüzden "Trigger" nesnemi "Order Details" tablosu üzerinde tanımlamalıyım. Yani "trigger" 'ım bu tabloyu izleyecek. İzleyecek ama bu tabloya "insert" işlemi yapılması olayını izleyecek. Bu yüzden tanımlarken "After Insert" diye tanımlamalıyım. Daha sonrası bildiğimiz t-sql dili, "Products" tablosunun "UnitsInStock" kolonundan sipariş edilen miktar kadar düşüreceğiz. Fakat arkadaşlar, "Order Details" tablosuna "insert" edilen son kaydın "Quantity" (miktar) değerini bilmem gerekir ki "Products" tablosunun "UnitsInStock" kolonundan bu değeri düşebileyim. Bunun için "Inserted" tablosundan yararlanacağım. Peki nedir bu "Inserted" tablosu? T-sql server dilinde "Inserted" ve "Deleted" tabloları vardır. Bu tabloları son eklenen veya son silinen kaydı tutan, tek satırlık tablolar olarak dişinebiliriz. Hangi tabloya eklendiyse veya hangi tablodan silindiyse o tablonun kolonları mevcuttur.

NOT: "Updated" tablosu yoktur arkadaşlar. Çünkü "update" işlemi, "delete" ve "insert" işlemleri olmak üzere iki aşamadan oluşur. Bir "update" işlemi gerçekleştiğinde ilk önce "delete" daha sonra arkasından "insert" işlemi gerçekleşir. Sonuç olarak "updated" tablosu yerine "deleted" ve "inserted" tabloları kullanılır.

Şimdi "trigger" nesnemizi oluşturalım.

ALTER TRIGGER StokGuncelle
ON dbo.[Order Details]
AFTER INSERT
AS 
      UPDATE dbo.Products
      SET UnitsInStock -= (SELECT Quantity FROM INSERTED)
      WHERE ProductID = (SELECT ProductId FROM INSERTED)
"StokGuncelle" adında "trigger" nesnem "Order Details" tablosu üzerinde oluştu. "Object Explorer" penceresinde aşağıda görüldüğü üzere, "Order Details" tablosu altında "Triggers" sekmesi altında, şimşek ikonuyla birlikte oluşturduk. 
Arkadaşlar eğer "trigger" nesnemin üzerinde "kırmızı ok" işareti yoksa "enable" durumdadır. Şimdi sıra geldi "trigger" nesnemi tetiklemeye.Dikkat ederseniz çağırmıyorum arkadaşlar tetikliyorum. Bir sipariş verelim bakalım. Ama öncesinde oluşturduğumuz "trigger" nesnesini tetiklemeden önce "Products" tablosundaki "ProductsId" değeri 1 olan ürünün stok değerine bir bakalım.

SELECT UnitsInStock FROM dbo.Products WHERE ProductID=1

Oluşturduğumuz "Trigger" nesnemizin doğru çalışıp çalışmadığını anlamak açısından, "trigger" 'ımızı tetikleyip aynı ürünün stoğuna tekrar bakalım. 1 nolu üründen 9 adet sipariş verelim. Eklenecek kaydı "Order Details" tablomda çok aramamak, tablomun en başında gözükmesi için "OrderId" 10248 verelim.

INSERT INTO dbo.[Order Details]
(OrderID ,ProductID ,UnitPrice ,Quantity ,Discount)
VALUES(10248, 1, 18, 9, 0)

"Insert" işleminden sonra bir adet "OrderDetails" tablosundan, bir adet de "Products" tablosundan olmak üzere iki satır etkilendi.

Emin olmak açısında sipariş verilen ürünümün stoğuna tekrar bakıyorum.
SELECT UnitsInStock FROM dbo.Products WHERE ProductID=1

Beklediğimiz gibi, görüldüğü üzere sipariş verilen ürünün stoğundan, sipariş miktarı kadar düşüldü. Yani "trigger" nesnemiz sorunsuz bir şekilde çalışıyor arkadaşlar.

Şimdi bir çok durum için bir "trigger" tanımlayalım. "Employees" tablosu üzerinde "insert, update ve delete" işlemlerinden sonra çalışsın. "After" yerine "for" yazsak da olur demiştik. Onu da yapalım. "Trigger" nesnemiz 
"Employees" tablosunda herhangi bir manipülasyon işleminde ekrana manipüle edilen kayıtları işlemiyle birlikte yazacaktır.

CREATE TRIGGER CalisanGuncelleme
ON dbo.Employees
FOR INSERT,UPDATE,DELETE
AS
      DECLARE @eskiisim NVARCHAR(20),@eskisoyisim NVARCHAR(20)
      DECLARE @yeniisim NVARCHAR(20),@yenisoyisim NVARCHAR(20),@eid INT
      IF(EXISTS(SELECT * FROM DELETED) AND EXISTS(SELECT * FROM INSERTED))
      BEGIN
            SELECT @eid=EmployeeID,@eskiisim=FirstName,@eskisoyisim=LastName 
FROM DELETED
            SELECT @yeniisim=FirstName,@yenisoyisim=LastName FROM INSERTED
            UPDATE dbo.Employees SET FirstName=@isim,LastName=@soyisim 
WHERE EmployeeID=@eid
            PRINT2 @eskiisim+ ' ' + @eskisoyisim + ' isimli calisan '+@eskiisim+' '+@eskisoyisim+' olarak guncellendi...'
      END
      ELSE IF(EXISTS(SELECT * FROM INSERTED))
      BEGIN
            SELECT @yeniisim=FirstName,@yenisoyisim=LastName FROM INSERTED
            PRINT @yeniisim+ ' ' + @yenisoyisim + ' isimli calisan eklendi...'
      END
      ELSE IF(EXISTS(SELECT * FROM DELETED))
      BEGIN
            SELECT @eskiisim=FirstName,@eskisoyisim=LastName FROM DELETED
            PRINT @eskiisim+ ' ' + @eskisoyisim + ' isimli calisan silindi...'
      END


NOT: MS Sql Server 'da iç içe 32 tane "trigger" nesnesi çalıştırılabilir.

Trigger Nesnenin Çalışmasını Durdurmak
Eğer "enable" durumdaki bir "trigger" nesnenizin çalışmasını istemiyorsanız ya disayndan yani "Object Explorer" penceresinden çalışmasının durmasını istediğimiz "trigger" nesneme sağ tık "disable" yapabilirim. Yada aşağıdaki kod satırı ile, "trigger" nesnem hangi database nesnesi üzerinde çalıştığını belirterek, "trigger" nesnemi "disable" edebilirim.

Başka bir yazıda görüşmek dileğiyle, hoşçakalın...

29 Nisan 2012 Pazar

MS SQL 'de Pagging (Sayfalama)

Merhaba arkadaşlar.
Bazı durumlar vardır ki sql server 'da tablolarınıza "select" işlemi yaptığınızda, tablolarınızdaki kayıtların hepsinin gelmesini istemezsiniz. Çünkü bazı tablolarında milyon kayıt olabilir. Hele ki bir web uygulamasından bir server 'a veri erişimi yapmaya çalışıyorsam, bu milyon kaydı "select" etmek bile ölümdür arkadaşlar. Bu kayıtlarınızın hepsinin gelmesi hem çok yavaş gelecektir, hem de bu kadar veriyi bir anda incelemek pek işinize yaramayacaktır. İşte arkadaşlar bu durumlar için t-sql dilinde "Pagging" (sayfalama) yapılır. Paging işlemi, getirmek istenilen verilerin tamamının yerine belirli kısımlarının sayfa sayfa getirilmesi işlemidir.

Ben bu örneğimde sayfalama işlemini yapan bir fonksiyon tanımlayacağım. Böylece sayfalama işlemi için her seferinde kod yazmayacağım, fonksiyonumu istediğim yerde çağırabilirim. ayrıca bu fonksiyonum 2 parametre alsın: birincisi "select" ettiğim sayfamın kaç satırdan oluşmasını istediğimi, ikinci parametresinde ise kaçıncı sayfamı "select" etmek istediğimi belirtiyorum.

Dikkat etmemiz gereken nokta id 'ye göre sıralamamız gerektiğidır. İleride bir kayıt silindiğinde id numarasında bir atlama meydana geleceğinden dolayı o sayfada kayıt sayısı eksik olacaktır. İşte bu neden kendi sıra kolonumuzu oluşturmalıyız. Bunu oluştururken parametre vermeden "ROW_NUMBER" fonksiyonunu kullanacağız. Bu fonksiyon bize birer birer artan bir kolon oluşturur. Ama oluşturacağımız kolonumuzun tablodaki hangi kolona göre sıra takip ettiğini belirtmemiz gerekir. Bu işlemi de "OVER(ORDER BY ProductID)" kod satırı ile "OVER" fonksiyonunu kullanarak yapacağız. Böylece "ProductID" kolonunu referans alarak satırlar sıralanarak gelecektir. Normalde de bir tabloya "select" çektiğimde "ProductID" kolonuna göre sıralı geliyor.

CREATE FUNCTION PagingSample(@satirSayisi INT,@sayfaNo INT)
RETURNS TABLE
AS
RETURN
      SELECT *
      FROM
      (
            SELECT ROW_NUMBER() OVER(ORDER BY ProductID) AS RowNumProductId,ProductName FROM Products
      ) AS CC
      WHERE RowNum BETWEEN (@sayfaNo-1) * @satirSayisi+
      AND (@sayfaNo) * @satirSayisi

"PaggingSample" fonksiyonumu tanımladım. İstediğim satırdan oluşan istedğim sayfasını çağırabiliriz. Örneğin 6 satırlık 2.sayfayı çağıralım.
GO
SELECT * FROM PagingSample(6,2)

Görüldüğü üzere fonksiyonumuz sorunsuz bir şekilde çalışıyor arkadaşlar. Farklı değerler için bir kere daha çalıştıralım. 3 kayıttan oluşan 8. sayfayı getirelim.
GO
SELECT * FROM PagingSample(3,8)

Umarım yardımcı olabilmişimdir. Başka bir yazıda görüşmek dileğiyle, hoşçakalın...

MS SQL 'de String Functions

Merhaba arkadaşlar.
Sql server 'da verileri listelemek için şimdiye kadar "select" ifadesi kullandık. Bunları bazen "view" bazen de "function" lar ile gerçekleştirdik. İhtiyacımıza göre kendi view yada fonksiyonumuzu oluşturmaktan ziyade, bizim için bu temel işleri sistemde hazır tanımlı "System Functions" fonksiyonlarını kullanarak yapabiliriz. İşte bu yazıda sistem fonksiyonları içerisinde tanımlı "String Functions" ları inceleyeceğiz. String fonksiyonlar, string ifadeleri istediğimiz şekilde manüpile ederek geriye bir değer döndürürler. String fonksiyonlar "Object Explorer" penceresinde tüm veritabanlarının altında "Programmabilty", "Functions", "System Functions", "String Functions" sekmesinin altında tanımlı halde bulunurlar.
Görüldüğü üzere hemen hemen hepsi c sharp 'tan gözümüze tanıdık gelmekte. Şimdi bu fonksiyonların bazılarını inceleyelim. Tabi ki herkes tarafından bilinen "Northwind" veritabanını kullanacağız. Ama önce şunu hatırlayalım. String bir ifadenin içinde ' (özel karakter) kullanmamız gerekiyorsa iki kere ('') kullanmalıyız.
SELECT 'Galatasaray''ın Şampiyonluğu'    --Galatasaray'ın Şampiyonluğu
  • LEN: Fonksiyonu bir string ifadenin uzunluğunu sayısal olarak döner. 
     SELECT FirstName,LEN(FirstName) FROM dbo.Employees   
          Şeklinde kullanılır. Personellerin adlarının uzunluğunu geriye döndürür. Fakat "len" fonksiyonu buşlukları saymaz. Aşağıdaki sorguda "len", 6 döner. 
     SELECT LEN('    Gaffar    ')  
     
          Peki ya sayısal bir kolonun uzunluğunu öğrenmeye çalışırsam. 
     SELECT LEN(UnitPrice),UnitPrice FROM dbo.Products
          Görüldüğü üzere "." (nokta) karakterini bile sayacaktır.
  • ToLower-ToUpper: "ToLower" string ifadeyi küçük harflerle, "ToUpper" ise büyük harflerle yazdırmaya yarar. 
     SELECT LOWER('GaFFaR SaLKıM')      --gaffar salkım
     SELECT UPPER('gAffAr sAlkIm')      --GAFFAR SALKIM
  • LTrim-RTrim: Sql server 'da, c sharp 'taki "Trim" fonksiyonu yoktur. Bunun yerine "LTrim" string ifadenin solundaki boşluklar, "RTrim" ise sağındaki boşlukları siler. İki taraftaki boşlukları da silmek isteniyorsa bu iki fonksiyonu içiçe kullanmak gerekir.
     SELECT LTRIM('    Gaffar    ')                  --Gaffar    
     SELECT RTRIM('    Gaffar    ')                  --    Gaffar
     SELECT RTRIM(LTRIM('    Gaffar Salkım    '))    --Gaffar
  • Reverse: String bir ifadeyi tersten yazdırır. 
     SELECT REVERSE('Gaffar Salkım')    --mıklaS raffaG
  • Substring: String bir ifadenin verdiğimiz index numarasından başlayarak, istediğimiz kadar karakterini almamızı sağlar. Geriye yine string bir ifade döner.
     SELECT SUBSTRING('Şampiyon Galatasaray',10,6)   --Galata
          Örneğin gelin personellerin adının son 3 harfini  yazdıralım.
     SELECT FirstName,SUBSTRING(FirstName,(LEN(FirstName)-2),3) FROM dbo.Employees

  • Space: Verilen sayı kadar boşluk karakteri atar.         
     SELECT 'Gaffar'+SPACE(5)+'Salkim'    --Gaffar   Salkim
  • Ascii: Verilen karakterin "ascii" karşılığını verir.
     SELECT ASCII('A')                    --65
  • Char: Verilen "ascii" kodun "char" karşılığını verir.
     SELECT CHAR(65)                      --A
  • CharIndex: Birinci parametresindeki stringin, ikinci stringdeki konumunu yani indexini döndürür. Bulamazsa 0 döndürür.
     SELECT CHARINDEX('büyük','En büyük Galatasaray')   --4  
  • Replicate: Verilen string ifadeyi, verilen sayı kadar tekrar ettirerek yazar.
     SELECT REPLICATE('OK',3)    --OKOKOK
  • Left: Verilen stringin başından verilen sayı kadar alır.
     SELECT LEFT('asa',2)        --as
  • Right:  Verilen stringin sonundan verilen sayı kadar alır.
     SELECT RIGHT('asa',2)       --sa
  • Stuff: Bu fonksiyon aşağıdaki örnekte 1. stringden 2. karakterinden başlayarak 3 karakter siler. Silinenler yerine 2. stringi koyar.
     SELECT STUFF('Gaffar',2,3,'Salkim')    --GSalkimar
  • Str: Verilen "double" sayıyı stringe dönüştürür. 1. parametresi "double" sayı, 2. 'si "double" sayının uzunluğu, 3. 'sü "decimal" kısmının uzunluğudur.
     SELECT STR(123.4,6,1)      --123.4

Umarım yardımcı olabilmişimdir.

Başka bir yazıda görüşmek dileğiyle, hoşçakalın...

28 Nisan 2012 Cumartesi

MS SQL 'de User Defined Functions-(3) Multistatement Table Valued Functions

Merhaba arkadaşlar.
"In Line Table Valued" fonksiyonlar geriye bir tablo döner  ve gövdesinde sadece "select" sorguları kullanılır demiştik. "User Defined" fonksiyonların sonuncusu olan "Multistatement Table Valued" (çoklu durum tablo değerli) fonksiyonları da geriye bir tablo döner. Fakat adından da anlaşılacağı üzere tanımlanırken gövdesinde DML dilinin tüm sorgularını (select, insert, update, delete) tümünü kullanabilir. Bunu yaparken de gövdesinin "begin-end" skopları arasında olması şarttır. "RETURNS" ifadesinden sonra geriye döndüreceği geçici bir tablo tanımlanır, tip olarak da "TABLE" tipi belirtilir. Bu yüzden en sonda "RETURN" 'den sonra bir şey yazmama gerek kalmaz. Bu tablonun kolonları tipleriyle birlikte tanımlanır. Tanımladığım bu tablo remde geçici olarak tutulur.

Örneğin bir fonksiyonumuz olsun. Parametre olarak verdiğimiz "ad" yada "soyad" 'a göre "Employees" tablosundan veriler çeksin. "Select" ile çektiği veriler aynı zamanda belirttiğimiz geçici tabloma da "insert" etsin. Burada dikkat edilmesi gereken nokta tabloma ekleyeceğim verilerin, tablomun sütün sayısına ve sütunlarımın tiplerine uygun olması gerektiğidir. 

CREATE FUNCTION Kisilerim(@tip nvarchar(7))
RETURNS @Tablom TABLE
(Id INT,Isim NVARCHAR(50))
AS
BEGIN
    IF(@tip='ad')
        BEGIN
            INSERT @Tablom SELECT EmployeeID,FirstName FROM dbo.Employees
        END
    ELSE IF(@tip='adsoyad')
        BEGIN
            INSERT @Tablom SELECT EmployeeID,FirstName+' '+LastName AS Isim 
            FROM dbo.Employees
        END
    RETURN
END

Fonksiyonum "Object Explorer" penceresinde "Nortwind" veritabanının altında "Programmability", "Functions", "Table-valued Functions" sekmesi altında yerini aldı. Fonksiyonumu kullanırken "Scalar" fonksiyonlarımdaki gibi "dbo" kullanmama gerek yoktur. İki sütunluk bir tablo döndürmek istediğim için "select" ile çağırıp istediği kolonları içerisinden çekebilirim.


SELECT * FROM Kisilerim('ad')          SELECT * FROM Kisilerim('adsoyad')                             

Örneğin ben tabloma kayıt girmeye çalışsam veya bir kaydımı silmeye çalışırsam "Employees" tablomda bir değişiklik olur mu?

ALTER FUNCTION Kisilerim(@tip nvarchar(7))
RETURNS @Tablom TABLE
(Id INT,Isim NVARCHAR(50))
AS
BEGIN
    IF(@tip='ad')
    BEGIN
        INSERT @Tablom SELECT EmployeeID,FirstName FROM dbo.Employees
    END
    ELSE IF(@tip='adsoyad')
    BEGIN
        INSERT @Tablom SELECT EmployeeID,FirstName+' '+LastName AS Isim 
FROM dbo.Employees
        DELETE FROM @Tablom WHERE Id=11
    END
RETURN
END

Hayır arkadaşlar, "Employees" tablomda bir değişiklik olmaz.  Fonksiyonumun tanımını değiştirirken geçici tablom üzerinde bir silme işlemi yaptığımdan dolayı, tablomu "select" ettiğimde bilgileri sadece filtreleyerek gösterecektir. Aşağıda görüldüğü üzere orjinal bilgi "Employees" tablomdadır.

SELECT * FROM Kisilerim('adsoyad')        SELECT * FROM dbo.Employees


Başka bir yazıda görüşmek dileğiyle, hoşçakalın...

MS SQL 'de User Defined Functions-(1) Scalar Valued Functions

Merhaba arkadaşlar.
"User Defined Functions" lardan ilki "Scalar" fonksiyonlarını inceleyeceğiz. "User Defined Functions" Giriş makalemde genel olarak fonksiyonlardan bahsetmiştik. Fonksiyonların birer veritabanı nesneleri olduğundan, bu yüzden DDL ile (create, alter, drop) yönetildiğinden. Geriye mutlaka değer döndürdüklerinden, bu sebeple "return" ve "returns" anahtar sözcüklerini kullanmamız gerektiğinden söz etmiştik. Bu hatırlatmalardan  sonra "Scalar" fonksiyonları adından da anlaşılacağı üzere geriye tek bir değer dönen fonksiyonlardır. Bu sebeple "returns" ifadesinden sonra geriye dönen değerin tipi belirtilir. Hemen basit bir örnek üzerinden konuyu kavramaya çalışalım. Oluştururken "CREATE" 'den sonra, nesnenin ne olduğunu yani "FUNCTION" yazmalıyım. Daha sonra fonksiyonumun ismini yazıyorum.

CREATE FUNCTION BugununTarihi()
RETURNS DATETIME
AS
BEGIN
      DECLARE @Tarih DATETIME
      set @Tarih= GETDATE()
      RETURN @Tarih
END

Fonsiyonumu parametresiz tanımladım. Geriye bugünün tarihini döndüreceğim için " RETURNS " 'den sonra "DATETIME" tipini belirttim. "AS" 'den sonra fonksiyonumun gövdesini "BEGIN" ve "END" skoplarının arasında tanımlamalıyım. "RETURN" diyip geriye değerini döndürmek istediğim değişkenin adını yazıyorum. En son fonksiyonumu çalıştırdım (execute).
Fonksiyonum başarılı bir şekilde oluşturuldu. "Object Explorer" penceresinde, database 'imin altında "Programmability", "Functions", "Scalar-valued Functions" sekmesinin altında imiyle birlikte yer aldı. Şimdi sıra geldi çalıştırmaya. Geriye tek değer döneceğim için "from" kullanmama gerek yok. "Select" yada "print" ile çağırabilirim. "Select"  ile çağırırsam "result" tipinde, "print" olarak çağırırsam "message" tipinde dönecektir. Fakat fonksiyonumu ikinci kısmıyla (dbo) birlikte çağırmalıyım, "Database Owner" olduğumu belirtmem gerek. Çağırmazsam "böyle bir fonksiyon tanımlı değil" hatası ile karşılaşırım. Bunun için "Scalar" fonksiyonlar "dbo.fonksiyonAdi" ile çağırılır.

SELECT dbo.BugununTarihi()

PRINT dbo.BugununTarihi()

Örneğin bir tane de parametre alan bir fonksiyon tanımlayalım. "Northwind" veritabanını kullanarak, hangi kategoriden kaç adet ürün satıldığını görelim.
CREATE FUNCTION KatAdet(@KatId INT)
RETURNS INT
AS
BEGIN
      RETURN 
      (SELECT SUM(dbo.[Order Details].Quantity) 
       FROM dbo.[Order Details]
       INNER JOIN dbo.Products 
       ON dbo.Products.ProductID=dbo.[Order Details].ProductID
       WHERE dbo.Products.CategoryID=@KatId)   
END 
SELECT CategoryName,dbo.KatAdet(CategoryId) AS 'Toplam Miktar' FROM Categories

Son örnek olarak bir fonksiyonumuz olsun. Parametre olarak verdiğimiz tarihi, istediğimiz formatta ve yine istediğimiz ayracı ay, gün ve yılın arasında kullanarak bize geri dönsün. Verdiğimiz tarihteki ay ve gün değeri tek haneliyse başına "0" eklesin. Bunun için ay ve günün uzunluğunu almalıyım. Uzunluğun "1" ise "string methods" kullanarak "0" ile "1" rakamlarını birleştirmeliyim. 
create function dbo.tarihFormatla
(@tarih datetime,@ayrac nchar(1),@format nchar(3))
returns nchar(10)
as
begin
      declare @yil nchar(4) = year(@tarih)
      declare @ay nchar(2) = month(@tarih)
      declare @gun nchar(2) = day(@tarih)
      declare @formatliTarih nchar(10)
      if len(@gun) = 1
            set @gun '0' @gun
      if len(@ay) = 1
            set @ay '0' @ay
           
      if @format = 'dmy'
            set @formatliTarih @gun @ayrac @ay @ayrac @yil
      else if @format = 'mdy'
          set @formatliTarih @ay @ayrac @gun @ayrac @yil
      else if @format = 'ymd'
          set @formatliTarih @yil @ayrac @ay @ayrac @gun
      return @formatliTarih
end
go
select dbo.tarihFormatla(getdate(),'/','ymd')

Başka bir yazıda görüşmek dileğiyle, hoşçakalın...