T-SQL - varsayılan parametrelerle işlev


155

Bu komut dosyası var:

CREATE FUNCTION dbo.CheckIfSFExists(@param1 INT, @param2 BIT = 1 )
RETURNS BIT
AS
BEGIN
    IF EXISTS ( bla bla bla )
        RETURN 1;
    RETURN 0;
END
GO

Bu şekilde bir prosedürde kullanmak istiyorum:

IF dbo.CheckIfSFExists( 23 ) = 0
    SET @retValue = 'bla bla bla';

Ama hatayı alıyorum:

Dbo.CheckIfSFExists yordamı veya işlevi için yetersiz sayıda bağımsız değişken sağlandı.

Neden çalışmıyor?

Yanıtlar:


227

böyle çağırmalısın

SELECT dbo.CheckIfSFExists(23, default)

Gönderen Technet'te :

Fonksiyonun bir parametresi varsayılan bir değere sahipse, varsayılan değeri almak için fonksiyon çağrıldığında VARSAYILAN anahtar sözcüğü belirtilmelidir. Bu davranış, parametrenin çıkarılmasının varsayılan değeri de içerdiği saklı yordamlarda varsayılan değerlere sahip parametreler kullanmaktan farklıdır. Bu davranış için bir istisna, EXECUTE deyimini kullanarak bir skaler işlevi çağırırken. EXECUTE kullanılırken, DEFAULT anahtar sözcüğü gerekli değildir.


80
Bunu görünce sinirliyim. defaultBurada konseptten yararlanamıyorum ... Şimdi gidip tüm yerleri değiştirmem gerekiyor.
LCJ

8
@ Lijo, yine de her çağrıda somut varsayılan değerinizi kopyalamamanın avantajını elde edersiniz.
Frédéric

9
Bindirmeye izin verilmediğimizden ve "varsayılan" sınırlı kullanılabilirliğe sahip olduğundan, çoğu zaman en iyi yaklaşım, ekstra parametrelerle yeni bir genişletilmiş sürüm oluşturmak (burada CheckIfSFExistsEX diyelim) ve orijinal işlevi sadece genişletilmiş sürümü "varsayılan" parametresiyle çağırmak. Bu şekilde TÜM mevcut kod çalışır ve bakım yapmak için yalnızca bir yeriniz vardır.
Eske Rahn

39

Üç yolla çağırabilirsiniz - DEFAULT ve EXECUTE ile parametrelerle

SET NOCOUNT ON;

DECLARE
@Table  SYSNAME = 'YourTable',
@Schema SYSNAME = 'dbo',
@Rows   INT;

SELECT dbo.TableRowCount( @Table, @Schema )

SELECT dbo.TableRowCount( @Table, DEFAULT )

EXECUTE @Rows = dbo.TableRowCount @Table

SELECT @Rows

11
DEFAULTAnahtar kelime neden seçilmeli, ancak yürütme sırasında atlanabilir? Bu berbat: / Umarım bu bir gün düzeltilecektir.
Misiu

@Misiu, "düzeltilmesi" gereken bir şey değil. Bu tasarım gereğidir. Her argümanı belirtmeden basitçe bir fonksiyonu çağırabilmenin "ideal" hedefine yaklaşmak için birçok alternatif okudum, ancak bunun neden gerekli olduğuna dair net bir açıklama görmedim. Kod açık olmalı ve bunu gerçekleştirmek için bir strateji kodlayıcının her zaman farkında olmasını gerektiren bir strateji olmalıdır. msgstr "% s: varsayılan değerler DEĞİŞTİRİLİR". Yani, IMO, bu iyi bir "kötü şey".
Gustavo Pinsard

16

Kullanıcı tanımlı işlevlerde, varsayılan bir değere sahip olsalar bile her parametreyi bildirmeniz gerekir.

Aşağıdakiler başarıyla yürütülür:

IF dbo.CheckIfSFExists( 23, default ) = 0
    SET @retValue = 'bla bla bla;

-1

Bu soruna geçici bir yol, bir çıkış parametresi ile saklı yordamlar kullanmaktır.

exec sp_mysprocname @returnvalue çıktı, @firstparam = 1, @ secondparam = 2

varsayılan olarak, saklı yordamın kendisinde ayarlanan varsayılanlara iletmediğiniz değerler. Ve sonuçları çıktı değişkeninizden alabilirsiniz.


1
Saklı bir yordam olarak işlevinizi değiştirmek genellikle iyi bir çözüm değildir, çünkü saklı yordam bir sorgu içinden çağrılamaz, ancak bir işlev olabilir.
Blade

Doğru, ancak tüm kod bloklarının bir sorgu içinden çağrılması gerekmez. Sql'nin işlevler için varsayılan değerleri işlemek için iyi bir yöntemi olmadığı gösterilmiştir (varsayılan anahtar kelimeyi kullanmak neredeyse bir değer eklemek kadar iştir). İyi bir genel çözüm değildir, ancak bazı kullanım durumlarında harika çalışır.
Jereme Guenther

İnsanlar bunu işaretlemeye devam ediyor, ama ben buna bağlı kalıyorum. Sorguların içinde çağrılmayacak yeniden kullanılabilir bir kod yığınına ihtiyacınız varsa ve varsayılan değerlerle gerçek isteğe bağlı parametrelerin esnekliğini istiyorsanız, saklı yordam yine de bir işlevden daha iyidir.
Jereme Guenther

1
Saklı yordamların kullanılması, bir işlev kullanmak yerine bunların kullanılması anlamına gelmez - saklı yordamın bir işlevin etrafına sarıcı olarak kullanılması anlamına gelebilir. Bu tekniği sık kullanıyorum; Varsayılan anahtar kelimeler artık proc içinde gizlidir. Bence bu fikir gayet iyi. Ayrıca, daha saf bir durumda bırakılabilen işlevden ayrı olarak, istersem daha karmaşık varsayılanlar yapmama izin verir.
J Bryan Price
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.