T-SQL - fonction avec paramètres par défaut

155

J'ai ce script:

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

Je souhaite l'utiliser dans une procédure de cette manière:

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

Mais j'obtiens l'erreur:

Un nombre insuffisant d'arguments a été fourni pour la procédure ou la fonction dbo.CheckIfSFExists.

Pourquoi ça ne marche pas?

nirmus
la source

Réponses:

227

tu dois l'appeler comme ça

SELECT dbo.CheckIfSFExists(23, default)

De Technet :

Lorsqu'un paramètre de la fonction a une valeur par défaut, le mot-clé DEFAULT doit être spécifié lors de l'appel de la fonction afin de récupérer la valeur par défaut. Ce comportement est différent de l'utilisation de paramètres avec des valeurs par défaut dans des procédures stockées dans lesquelles l'omission du paramètre implique également la valeur par défaut. Une exception à ce comportement se produit lors de l'appel d'une fonction scalaire à l'aide de l'instruction EXECUTE. Lorsque vous utilisez EXECUTE, le mot clé DEFAULT n'est pas obligatoire.

SQLMenace
la source
80
Voyant cela, je suis frustré. Je ne profite pas du defaultconcept ici ... Je dois changer tous les endroits maintenant.
LCJ
8
@Lijo, vous avez toujours l'avantage de ne pas dupliquer votre valeur par défaut concrète à chaque appel.
Frédéric
9
Comme nous ne sommes pas autorisés à superposer, et que la "valeur par défaut" a donc une facilité d'utilisation limitée, la meilleure approche sera souvent de créer une nouvelle version étendue avec un suffixe (disons CheckIfSFExistsEX ici) avec les paramètres supplémentaires, et de changer la fonction d'origine en juste appel de la version étendue avec le paramètre "default". De cette façon, TOUT le code existant fonctionne et vous n'avez qu'un seul endroit à gérer.
Eske Rahn
39

Vous pouvez l'appeler de trois façons - avec paramètres, avec DEFAULT et via 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
la source
11
Pourquoi le DEFAULTmot-clé est-il requis dans select, mais peut-il être omis dans execute? Cela craint: / J'espère que cela sera corrigé un jour.
Misiu le
@Misiu, ce n'est pas quelque chose qui doit être "corrigé". C'est par conception. J'ai lu beaucoup d'alternatives pour aborder un objectif «idéal» de pouvoir simplement appeler une fonction sans spécifier chaque argument, mais je n'ai pas vu d'explication claire sur la raison pour laquelle cela est nécessaire. Le code doit être clair et une stratégie pour y parvenir nécessite que le codeur soit toujours conscient que "hé, vous appelez une fonction qui a ceci et ces autres arguments, qui ont des valeurs par défaut. N'oubliez pas que le les valeurs par défaut PEUVENT ÊTRE CHANGÉES ". Donc, l'OMI, c'est une bonne "mauvaise chose" à avoir.
Gustavo Pinsard le
16

Avec les fonctions définies par l'utilisateur, vous devez déclarer tous les paramètres, même s'ils ont une valeur par défaut.

Ce qui suit s'exécuterait avec succès:

IF dbo.CheckIfSFExists( 23, default ) = 0
    SET @retValue = 'bla bla bla;
Sec
la source
-1

Une façon de contourner ce problème consiste à utiliser des procédures stockées avec un paramètre de sortie.

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

valeurs que vous ne transmettez pas par défaut aux valeurs par défaut définies dans la procédure stockée elle-même. Et vous pouvez obtenir les résultats de votre variable de sortie.

Jereme Guenther
la source
1
Changer votre fonction en une procédure stockée n'est en général pas une bonne solution, car une procédure stockée ne peut pas être appelée à partir d'une requête, mais une fonction peut.
Blade
Certes, tous les blocs de code n'ont pas besoin d'être appelés à partir d'une requête. Il a été démontré que sql n'a pas une bonne méthode de gestion des valeurs par défaut pour les fonctions (l'utilisation du mot-clé default représente presque autant de travail que l'ajout d'une valeur). Ce n'est pas une bonne solution générale, mais cela fonctionne très bien dans certains cas d'utilisation.
Jereme Guenther
Les gens continuent de marquer cela, mais je m'y tiens. Si vous avez besoin d'un morceau de code réutilisable, qui ne sera pas appelé à l'intérieur des requêtes, et que vous voulez la flexibilité de vrais paramètres facultatifs avec des valeurs par défaut, une procédure stockée est toujours meilleure qu'une fonction.
Jereme Guenther
1
Utiliser des procédures stockées ne signifie pas les utiliser au lieu d'utiliser une fonction - cela peut signifier utiliser la procédure stockée comme wrapper autour d'une fonction. J'utilise souvent cette technique; les mots-clés par défaut sont maintenant cachés dans le proc. Je pense que cette idée est très bien. Cela me permet également de faire des valeurs par défaut plus compliquées si je le souhaite - séparément de la fonction, qui peut être laissée dans un état plus pur.
J Bryan Price