Fonksiyonlar ve Saklanan Prosedürler


88

Diyelim ki sonuç olarak bir tablo döndürmesi gereken bir T-SQL kodu uygulamam gerekiyor. Tablo değerli bir işlevi veya bir dizi satır döndüren bir saklı yordamı uygulayabilirim. Ne kullanmalıyım?

Kısaca bilmek istediğim şey şu:

İşlevler ve depolanan yordamlar arasındaki temel farklar nelerdir? Birini veya diğerini kullanırken nelere dikkat etmeliyim?


1
Bu mükemmel bir cevap gibi görünüyor: stackoverflow.com/a/1179778/365188
Ozair Kafray

Yanıtlar:


51

Bu kod parçasının sonucunu diğer tablolarla birleştirmek isteyecekseniz, tabii ki tablo değerli bir işlev sonuçları tek bir SELECT deyiminde oluşturmanıza izin verecektir.

Genellikle bir hiyerarşi vardır (Görünüm <TV İşlevi <Depolanan Proc). Her birinde daha fazlasını yapabilirsiniz, ancak çıktıları oluşturma ve optimize edicinin gerçekten dahil olma yeteneği, işlevsellik arttıkça azalır.

Bu nedenle, hangisi en az istediğiniz sonucu ifade etmenize izin veriyorsa onu kullanın.


50

Fonksiyonlar belirleyici olmalıdır ve veritabanında değişiklik yapmak için kullanılamaz, oysa saklı prosedürler ekleme ve güncelleme vb. Yapmanıza izin verir.

Büyük, karmaşık sorgular için büyük bir ölçeklenebilirlik sorunu oluşturduğundan, işlev kullanımınızı sınırlamalısınız. Sorgu iyileştirici için bir tür "kara kutu" haline gelirler ve işlevleri kullanmak ile kodu bir sorguya eklemek arasında büyük performans farkları göreceksiniz.

Ancak çok özel durumlarda tablo değerli iadeler için kesinlikle faydalıdırlar.

Virgülle ayrılmış bir listeyi ayrıştırmanız gerekirse, bir diziyi bir prosedüre geçirmeyi simüle etmek için, bir işlev listeyi sizin için bir tabloya dönüştürebilir. Bu, Sql Server 2005'te yaygın bir uygulamadır, çünkü tabloları henüz saklı yordamlara geçiremiyoruz (2008 ile yapabiliriz).


1
Ancak depolanan bir prosedüre XML gönderebilirsiniz: stackoverflow.com/questions/144550/…
cllpse

2
Yanlış, çoğu SQL sunucusu işlevi, MS-SQL sunucusundaki getdate gibi belirleyici değildir. Yalnızca ODBC işlevleri kanonik işlevlerdir (= çok daha hızlı + indekslenebilir) ... Ancak çok haklısınız, performans nedenlerinden ötürü sorgularda işlevlerin kullanımını mümkün olduğunca sınırlandırmalısınız.
Stefan Steiger

45

Dokümanlardan :

Bir saklı yordam aşağıdaki ölçütleri karşılıyorsa, tablo değerli bir işlev olarak yeniden yazılmak için iyi bir adaydır:

  • Mantık, tek bir SELECT deyiminde ifade edilebilir, ancak yalnızca parametrelere duyulan ihtiyaç nedeniyle bir görünümden ziyade saklı bir yordamdır.

  • Depolanan yordam, tablo değişkenleri dışında güncelleme işlemleri gerçekleştirmez.

  • Dinamik EXECUTE komutlarına gerek yoktur.

  • Depolanan yordam, bir sonuç kümesi döndürür.

  • Depolanan yordamın birincil amacı, geçici bir tabloya yüklenecek ve daha sonra bir SELECT deyiminde sorgulanacak ara sonuçlar oluşturmaktır.


12

Saklanan prosedürler ve işlevler arasında birkaç ilginç fark yazacağım.

  • Fonksiyonları seçili sorgularda kullanabiliriz ancak saklı yordamları seçili sorgularda kullanamayız.
  • Fonksiyonlarda deterministik olmayan fonksiyonları kullanamayız, ancak depolanan prosedürlerde deterministik olmayan fonksiyonları kullanabiliriz. Şimdi soru ortaya çıkıyor, deterministik olmayan fonksiyon nedir .. Ans: -

    Belirleyici olmayan bir işlev, getdate () gibi farklı zamanlarda aynı girdi değerleri için farklı çıktılar döndüren işlevdir. Her çalıştırıldığında her zaman farklı bir değer döndürür.

    İstisna:-

    Sql 2000'den önceki sql server'ın önceki sürümleri, kullanıcı tanımlı işlevlerde getdate () işlevinin kullanılmasına izin vermez, ancak sürüm 2005 ve sonrası, kullanıcı tanımlı bir işlev içinde getdate () işlevini kullanmamıza izin verir.

    Newid () deterministik olmayan işlevin başka bir örneğidir, ancak kullanıcı tanımlı işlevlerde kullanılamaz, ancak saklı yordamda kullanabiliriz.

  • DML (insert, update, delete) deyimlerini bir saklı yordam içinde kullanabiliriz, ancak DML deyimlerini fiziksel tablolardaki veya kalıcı tablolardaki işlevlerde kullanamayız. Fonksiyonlarda DML işlemi yapmak istiyorsak, bunu kalıcı tablolar üzerinde değil tablo değişkenleri üzerinden yapabiliriz.

  • Hata işlemeyi işlev içinde kullanamayız, ancak saklı yordamlarda hata işleme yapabiliriz.


MySQL işlevlerinde DML işlemleri nasıl desteklenir?
Joey Pinto

@Filmdenkare Çünkü myNONsql SQL şikayeti değildir. Elbette, ekstraları var, ancak temelleri yok.
PerformanceDBA

8
  1. Prosedür sıfır veya n değerleri döndürebilirken, işlev zorunlu olan bir değeri döndürebilir.

  2. Prosedürlerin giriş / çıkış parametreleri olabilirken, işlevler yalnızca giriş parametrelerine sahip olabilir.

  3. Prosedür, seçimin yanı sıra DML ifadesine izin verirken işlev, içinde yalnızca select ifadesine izin verir.

  4. Fonksiyonlar prosedürden çağrılabilirken prosedürler fonksiyondan çağrılamaz.

  5. Bir prosedürdeki try-catch bloğu tarafından istisna ele alınabilirken, try-catch bloğu bir fonksiyonda kullanılamaz.

  6. Prosedürde işlem yönetimine gidebiliriz ama işleve gidemeyiz.

  7. Prosedürler bir select deyiminde kullanılamazken, işlev bir select deyimine gömülebilir.

  8. UDF (Kullanıcı Tanımlı işlev), WHERE/ HAVING/ SELECTbölümünde herhangi bir yerde SQL deyimlerinde kullanılabilir, oysa saklı yordamlar olamaz.

  9. Tablo döndüren UDF'ler başka bir satır kümesi olarak değerlendirilebilir. Bu, JOINdiğer tablolarla birlikte s'de kullanılabilir .

  10. Satır içi UDF'ler, parametreleri alan görünümler olabilir ve JOINs ve diğer satır kümesi işlemlerinde kullanılabilir.


6

Bir işleviniz varsa, örneğin SQL deyiminizin bir parçası olarak kullanabilirsiniz.

SELECT function_name(field1) FROM table

Saklanan yordamlar için bu şekilde çalışmaz.


1
Tablo değerlerini döndüren fonksiyonlardan bahsettiğini düşünüyorum.
wcm

1
Genel olarak konuşuyorum. Ancak benim özel durumum için şu anda bir saklı yordam veya tablo değerli bir işlev arasındayım.
Auron

5

Hem bir Tablo Değerli İşlevde hem de Saklanan Yordamda çalışan aynı kod biti (uzun bir SELECT deyimi) ve düz bir EXEC / SELECT ve her biri aynı şekilde gerçekleştirilen uzun süreli bir mantık biti ile bazı testler yaptım.

Kanımca, bir sonuç kümesini döndürmek için saklı yordam yerine her zaman Tablo Değerli İşlev kullanın, çünkü daha sonra bunlarla birleşen sorgularda mantığı çok daha kolay ve okunabilir hale getirir ve aynı mantığı yeniden kullanmanızı sağlar. Çok fazla performans vuruşunu önlemek için, işlevin sonuç kümesini daha hızlı döndürmesini sağlamak için genellikle "isteğe bağlı" parametreler (yani bunlara NULL geçirebilirsiniz) kullanırım, örneğin:

CREATE FUNCTION dbo.getSitePermissions(@RegionID int, @optPersonID int, optSiteID int)
AS
RETURN 
    SELECT DISTINCT SiteID, PersonID
    FROM dbo.SiteViewPermissions
    WHERE (@optPersonID IS NULL OR @optPersonID = PersonID)
    AND (@optSiteID IS NULL OR @optSiteID = SiteID)
    AND @RegionID = RegionID

Bu şekilde, bu işlevi birçok farklı durum için kullanabilirsiniz ve büyük bir performans darbesi almayın. Bunun daha sonra filtrelemekten daha verimli olduğuna inanıyorum:

SELECT * FROM dbo.getSitePermissions(@RegionID) WHERE SiteID = 1

Bu tekniği birkaç işlevde, bazen bu türden "isteğe bağlı" parametrelerin uzun bir listesiyle kullandım.


4

Tüm geri döndüğüm tek bir tablo olduğunda kişisel olarak tablo değerli fonksiyonları kullanıyorum. Temelde onlara parametreli görünümler gibi davranıyorum.

Döndürülen birden fazla kayıt kümesine ihtiyacım olursa veya tablolarda güncellenen değerler olacaksa, bir saklı yordam kullanırım.

2 sentim


4

Yukarıda belirtildiği gibi, işlevler daha okunabilir / bir araya getirilebilir / kendi kendini belgelendirebilir, ancak genel olarak daha az performanslıdır ve aşağıdaki gibi birleştirmelerde kendilerinden uzaklaşırsanız ciddi şekilde daha az performans gösterebilir.

SELECT *
FROM dbo.tvfVeryLargeResultset1(@myVar1) tvf1
INNER JOIN dbo.tvfVeryLargeResultset1(@myVar2) tvf2
    ON (tvf1.JoinId = tvf2.JoinId)

Çoğu zaman, bir tvf'nin ortadan kaldırabileceği (kabul edilemez bir performans maliyetiyle) kod fazlalığını kabul etmeniz yeterlidir.

Henüz bahsetmediğim bir diğer nokta, çoklu ifadeli bir tvf içinde veritabanı durum değiştiren geçici tabloları kullanamayacağınızdır. Bir geçici tabloya işlevsel olarak en eşdeğer mekanizma, bellek tablosu değişkenindeki durum değiştirmedir ve büyük veri kümeleri için, bir geçici tablo muhtemelen bir tablo değişkeninden daha yüksek performanslı olacaktır. (Diğer alternatifler arasında dinamik tablolar ve ortak tablo değerli ifadeler bulunur, ancak bir miktar karmaşıklıkta bunlar iyi bir seçenek IMO olmaktan çıkar.)


1

Ben performans ikisini de test ederdim. Muhtemelen sp yaklaşımı veya türetilmiş bir tablo bir fonksiyondan önemli ölçüde daha hızlı olacaktır ve eğer öyleyse bu yaklaşım kullanılmalıdır. Genelde performans domuzları olabileceğinden işlevlerden kaçınırım.


1

Şuna bağlıdır :) Tablo değerli sonucu başka bir prosedürde kullanmak istiyorsanız, TableValued İşlevini kullanmanız daha iyidir. Sonuçlar bir müşteri içinse, depolanan işlem genellikle daha iyi bir yoldur.


-1

Depolanan prosedürler, daha hızlı çalışan ve sql enjeksiyonlarından tasarruf sağlayan önceden derlenmiş sorgulardır. 0 veya N değerleri döndürebilirler. Depolanan prosedürler içerisinde DML işlemlerini gerçekleştirebiliriz. Prosedürlerin içindeki fonksiyonları kullanabilir ve seçme sorgusunda fonksiyonları kullanabiliriz. İşlevler, herhangi bir değeri döndürmek için kullanılır ve işlevlerde DML işlemleri mümkün değildir. fonksiyonlar skaler ve tablo değerli olmak üzere iki türdendir. skaler işlev, tablo satırlarını döndürmek için kullanılan tek bir değer, tablo değerli işlev döndürür.


Bu, çok sayıda yanıtı olan çok eski bir sorudur, çoğu (kabul edilen yanıt dahil) oldukça olumlu oylanmıştır. Böyle bir ileti dizisine başka bir yanıt eklemeden önce kendinize şu soruyu sormalısınız: "Başka bir yanıt yazmamı gerektiren tüm bu mevcut yanıtlarda eksik olan nedir?"
APC
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.