T-SQL - funkcja z domyślnymi parametrami


155

Mam ten skrypt:

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

Chcę to wykorzystać w procedurze w ten sposób:

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

Ale pojawia się błąd:

Podano niewystarczającą liczbę argumentów dla procedury lub funkcji dbo.CheckIfSFExists.

Dlaczego to nie działa?

Odpowiedzi:


227

musisz to tak nazwać

SELECT dbo.CheckIfSFExists(23, default)

Od Technet :

Gdy parametr funkcji ma wartość domyślną, słowo kluczowe DEFAULT musi być określone podczas wywoływania funkcji, aby pobrać wartość domyślną. To zachowanie różni się od używania parametrów z wartościami domyślnymi w procedurach składowanych, w których pominięcie parametru oznacza również wartość domyślną. Wyjątkiem od tego zachowania jest wywołanie funkcji skalarnej za pomocą instrukcji EXECUTE. Podczas korzystania z EXECUTE słowo kluczowe DEFAULT nie jest wymagane.


80
Widząc to, jestem sfrustrowany. Nie korzystam defaulttutaj z koncepcji ... Muszę teraz zmienić wszystkie miejsca.
LCJ

8
@Lijo, nadal masz tę zaletę, że nie powielasz swojej konkretnej wartości domyślnej przy każdym połączeniu.
Frédéric

9
Ponieważ nie wolno nam nakładać, a „domyślne” ma ograniczoną użyteczność, często najlepszym podejściem będzie utworzenie nowej rozszerzonej wersji z sufiksem (powiedzmy tutaj CheckIfSFExistsEX) z dodatkowymi parametrami i zmiana oryginalnej funkcji na po prostu wywołanie wersji rozszerzonej z parametrem „default”. W ten sposób CAŁY istniejący kod działa i masz tylko jedno miejsce do utrzymania.
Eske Rahn

39

Możesz to nazwać na trzy sposoby - z parametrami, z DEFAULT i przez EXECUTE

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
Dlaczego DEFAULTsłowo kluczowe jest wymagane w select, ale można je pominąć w wykonaniu? To jest do bani: / Miejmy nadzieję, że zostanie to kiedyś naprawione.
Misiu

@Misiu, to nie jest coś, co trzeba „naprawiać”. To jest zgodne z projektem. Czytałem wiele alternatyw, aby zbliżyć się do „idealnego” celu, jakim jest po prostu możliwość wywołania funkcji bez podawania każdego argumentu, ale nie widziałem jasnego wyjaśnienia, dlaczego jest to wymagane. Kod powinien być jasny, a jedną ze strategii, aby to osiągnąć, jest wymaganie od programisty, aby zawsze był świadomy, że „hej, wywołujesz funkcję, która MA TAKIE i inne argumenty, które mają wartości domyślne. Nie zapominaj, że wartości domyślne MOGĄ BYĆ ZMIENIONE ”. Więc IMO, to dobra „zła rzecz”.
Gustavo Pinsard

16

W przypadku funkcji zdefiniowanych przez użytkownika musisz zadeklarować każdy parametr, nawet jeśli mają one wartość domyślną.

Następujące czynności zostałyby wykonane pomyślnie:

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

-1

Jednym ze sposobów obejścia tego problemu jest użycie procedur składowanych z parametrem wyjściowym.

exec sp_mysprocname @returnvalue output, @firstparam = 1, @ secondparam = 2

wartości, które nie są przekazywane domyślnie do wartości domyślnych ustawionych w samej procedurze składowanej. Wyniki można uzyskać ze zmiennej wyjściowej.


1
Zmiana funkcji na procedurę składowaną nie jest na ogół dobrym rozwiązaniem, ponieważ procedury składowanej nie można wywołać z poziomu zapytania, ale funkcja może.
Blade

To prawda, ale nie wszystkie bloki kodu muszą być wywoływane z poziomu zapytania. Wykazano, że sql nie ma dobrej metody obsługi wartości domyślnych funkcji (użycie słowa kluczowego default wymaga prawie tyle samo pracy, co dodanie wartości). Nie jest to dobre rozwiązanie ogólne, ale świetnie sprawdza się w niektórych przypadkach.
Jereme Guenther

Ludzie wciąż to zaznaczają, ale ja się tego trzymam. Jeśli potrzebujesz fragmentu kodu wielokrotnego użytku, który nie będzie wywoływany wewnątrz zapytań, i potrzebujesz elastyczności prawdziwych parametrów opcjonalnych z wartościami domyślnymi, procedura składowana jest nadal lepsza niż funkcja.
Jereme Guenther

1
Korzystanie z procedur składowanych nie oznacza używania ich zamiast korzystania z funkcji - może to oznaczać użycie procedury składowanej jako opakowania wokół funkcji. Często używam tej techniki; te domyślne słowa kluczowe są teraz ukryte wewnątrz proc. Myślę, że ten pomysł jest w porządku. Pozwala mi również na bardziej skomplikowane ustawienia domyślne, jeśli chcę - niezależnie od funkcji, którą można pozostawić w bardziej czystym stanie.
J Bryan Price
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.