Je veux obtenir une valeur d'une fonction en utilisant une instruction case. J'ai essayé ce qui suit mais cela ne fonctionne pas:
CREATE FUNCTION [FATMS].[fnReturnByPeriod]
(
@Period INT
)
RETURNS int
AS
BEGIN
SELECT CASE @Period
when 1 then 1
when @Period >1 and @Period <=7 then 1
when @Period >7 and @Period <=30 then 1
when @Period >30 and @Period<=90 then 1
when @Period >90 and @Period <=180 then 1
when @Period >180 and @Period <=360 then 1
else 0
END
RETURN @Period
END
Il existe deux types de expression CASE : simple et recherché. Vous devez choisir l'un ou l'autre - vous ne pouvez pas utiliser un mélange des deux types dans une expression.
Essaye ça:
SELECT CASE
WHEN @Period = 1 THEN 1
WHEN @Period > 1 AND @Period <= 7 THEN 2
WHEN @Period > 7 AND @Period <= 30 then 3
-- etc...
ELSE 0
END
En outre, vous devez attribuer le résultat à quelque chose comme d'autres l'ont déjà souligné.
Lorsque vous utilisez RETURN @Period, vous devez affecter une valeur à @Period. L'exemple suivant montre comment structurer votre code de sorte qu'il n'est pas nécessaire de déclarer une variable locale.
CREATE FUNCTION [FATMS].[fnReturnByPeriod]
(
@Period INT
)
RETURNS INT
AS
BEGIN
RETURN
CASE
WHEN @Period = 1 THEN 1
WHEN @Period > 1 AND @Period <=7 THEN 1
WHEN @Period > 7 AND @Period <=30 THEN 1
WHEN @Period > 30 AND @Period<=90 THEN 1
WHEN @Period > 90 AND @Period <=180 THEN 1
WHEN @Period > 180 AND @Period <=360 THEN 1
ELSE 0
END
END
Déclarez une deuxième variable, puis définissez cette valeur car vous ne réinitialisez pas @Period
.
Par exemple:
DECLARE @Output AS INT
SELECT @Output = CASE @Period
WHEN 1 then 1
WHEN @Period > 1 AND @Period <= 7 THEN 1 -- Should be 2
WHEN @Period > 7 AND @Period <= 30 THEN 1 -- Should be 3
WHEN @Period > 30 AND @Period<= 90 THEN 1 -- Should be 4
WHEN @Period > 90 AND @Period <= 180 THEN 1 -- Should be 5
WHEN @Period > 180 AND @Period <= 360 THEN 1 -- Should be 6
ELSE 0 END;
RETURN @Output;
Je l'ai laissé comme ça car je suppose que vous allez changer vos valeurs pour chacune de ces instructions CASE
.
Vous n'affectez @Period nulle part. Essayez avec when @Period >1 and @Period <=7 then SET @Period = 1
et par la suite pour toutes les autres lignes.
SQL n'a pas de retours implicites et vous devez donc toujours définir les variables avant de les renvoyer.
Voici une approche basée sur SET pour écrire votre fonction dans SQL Server 2008
CREATE FUNCTION [FATMS].[fnReturnByPeriod]
(
@Period INT
)
RETURNS int
AS
BEGIN
return isnull((SELECT min(v)
from (values
(1,1),
(7,2),
(30,3),
(90,4),
(180,5),
(360,6)) t(n,v)
where n >= @Period and @period>0), 0)
END
De la façon dont vous l'avez écrit, toutes les branches CASE renvoient 1, donc vous pourriez aussi bien utiliser
return case when @period between 1 and 360 then 1 else 0 end
En quoi cela "ne fonctionne pas"? Cela produit-il une erreur lorsque vous essayez de l'exécuter? Retourne-t-il un résultat inattendu?
Du haut de ma tête, il y a plusieurs problèmes:
Votre déclaration de cas renvoie 1
dans tous les cas.
L'instruction case combine également deux types différents de sémantique CASE
:
CASE @Period
WHEN <condition> THEN <result>
WHEN <other condition> THEN <result>
ELSE <result>
END
ou
CASE
WHEN @Period = <value> THEN <result>
WHEN @Period = <other value> THEN <result>
ELSE <result>
END
Le second formulaire vous permet d'utiliser des conditions indépendantes, tandis que le premier ne peut vérifier que différentes valeurs de @Period
.
En outre, vous renvoyez la valeur de @Period, pas la valeur générée par l'instruction CASE.