T-SQL - Funktion mit Standardparametern

155

Ich habe dieses Skript:

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

Ich möchte es in einer Prozedur folgendermaßen verwenden:

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

Aber ich bekomme den Fehler:

Für die Prozedur oder Funktion dbo.CheckIfSFExists wurde nicht genügend Argumente angegeben.

Warum funktioniert es nicht?

Nirmus
quelle

Antworten:

227

du musst es so nennen

SELECT dbo.CheckIfSFExists(23, default)

Von Technet :

Wenn ein Parameter der Funktion einen Standardwert hat, muss beim Aufruf der Funktion das Schlüsselwort DEFAULT angegeben werden, um den Standardwert abzurufen. Dieses Verhalten unterscheidet sich von der Verwendung von Parametern mit Standardwerten in gespeicherten Prozeduren, bei denen das Weglassen des Parameters auch den Standardwert impliziert. Eine Ausnahme von diesem Verhalten ist das Aufrufen einer Skalarfunktion mithilfe der EXECUTE-Anweisung. Bei Verwendung von EXECUTE ist das Schlüsselwort DEFAULT nicht erforderlich.

SQLMenace
quelle
79
Als ich das sehe, bin ich frustriert. Ich bekomme hier keinen Vorteil aus dem defaultKonzept ... Ich muss jetzt alle Orte wechseln.
LCJ
8
@Lijo, Sie haben immer noch den Vorteil, dass Sie Ihren konkreten Standardwert nicht bei jedem Aufruf duplizieren.
Frédéric
9
Da wir nicht überlagern dürfen und der "Standard" daher nur eine eingeschränkte Benutzerfreundlichkeit aufweist, besteht der beste Ansatz häufig darin, eine neue erweiterte Version mit einem Suffix (hier CheckIfSFExistsEX hier) mit den zusätzlichen Parametern zu erstellen und die ursprüngliche Funktion auf "Just" zu ändern Aufrufen der erweiterten Version mit dem Parameter "default". Auf diese Weise funktioniert ALLER vorhandene Code, und Sie müssen nur einen Ort pflegen.
Eske Rahn
39

Sie können es auf drei Arten aufrufen - mit Parametern, mit DEFAULT und über 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
Douglas Osborne
quelle
11
Warum wird das DEFAULTSchlüsselwort in select benötigt, kann aber in execute weggelassen werden? Das ist scheiße: / Hoffentlich wird das eines Tages behoben.
Misiu
@ Misiu, es ist nicht etwas, das "repariert" werden muss. Das ist beabsichtigt. Ich habe viele Alternativen gelesen, um mich einem "idealen" Ziel zu nähern, einfach eine Funktion aufrufen zu können, ohne jedes Argument anzugeben, aber ich habe keine klare Erklärung dafür gesehen, warum dies erforderlich ist. Der Code sollte klar sein und eine Strategie, um dies zu erreichen, besteht darin, dass der Codierer immer wissen muss, dass "hey, Sie rufen eine Funktion auf, die dieses und jenes andere Argumente hat, die zufällig Standardwerte haben. Vergessen Sie nicht, dass das Standardwerte können geändert werden ". Also, IMO, das ist eine gute "schlechte Sache".
Gustavo Pinsard vor
16

Bei benutzerdefinierten Funktionen müssen Sie jeden Parameter deklarieren, auch wenn er einen Standardwert hat.

Folgendes würde erfolgreich ausgeführt:

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

Eine Möglichkeit, dieses Problem zu umgehen, besteht darin, gespeicherte Prozeduren mit einem Ausgabeparameter zu verwenden.

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

Werte, die Sie standardmäßig nicht an die in der gespeicherten Prozedur selbst festgelegten Standardeinstellungen übergeben. Und Sie können die Ergebnisse von Ihrer Ausgabevariablen erhalten.

Jereme Günther
quelle
1
Das Ändern Ihrer Funktion in eine gespeicherte Prozedur ist im Allgemeinen keine gute Lösung, da eine gespeicherte Prozedur nicht aus einer Abfrage heraus aufgerufen werden kann, eine Funktion jedoch.
Blade
Es stimmt, jedoch müssen nicht alle Codeblöcke innerhalb einer Abfrage aufgerufen werden. Es hat sich gezeigt, dass SQL keine gute Methode zum Behandeln von Standardwerten für Funktionen bietet (die Verwendung des Standardschlüsselworts ist fast so aufwändig wie das Hinzufügen eines Werts). Es ist keine gute allgemeine Lösung, funktioniert aber in bestimmten Anwendungsfällen hervorragend.
Jereme Günther
Die Leute notieren das immer wieder, aber ich bleibe dabei. Wenn Sie einen wiederverwendbaren Codeabschnitt benötigen, der nicht in Abfragen aufgerufen wird, und die Flexibilität echter optionaler Parameter mit Standardwerten wünschen, ist eine gespeicherte Prozedur immer noch besser als eine Funktion.
Jereme Günther
1
Die Verwendung gespeicherter Prozeduren bedeutet nicht, sie anstelle einer Funktion zu verwenden - es kann bedeuten, dass die gespeicherte Prozedur als Wrapper um eine Funktion verwendet wird. Ich benutze diese Technik oft; Die Standardschlüsselwörter sind jetzt im Prozess ausgeblendet. Ich denke, diese Idee ist in Ordnung. Außerdem kann ich auf Wunsch kompliziertere Standardeinstellungen vornehmen - getrennt von der Funktion, die in einem reineren Zustand belassen werden kann.
J Bryan Price