web-dev-qa-db-fra.com

Si autre si dans une fonction serveur SQL

J'ai cette fonction que j'essaye de créer. Lorsque je l’analyse, cela fonctionne bien, mais pour créer la fonction dans la base de données, il est indiqué que mes noms de colonne ne sont pas valides. Ce n'est pas vrai, je les ai épelés correctement. Voici le code:

ALTER FUNCTION [dbo].[fnTally] (@SchoolId nvarchar(50))
RETURNS int

AS 

BEGIN 

DECLARE @Final nvarchar
IF EXISTS (

    SELECT 
        question, 
        yes_ans, 
        no_ans, 
        na_ans, 
        blank_ans 
    FROM dbo.qrc_maintally 
    WHERE school_id = @SchoolId 

)

    IF yes_ans > no_ans AND yes_ans > na_ans 
    BEGIN
        SET @Final = 'Yes'
    END

    ELSE IF no_ans > yes_ans AND no_ans > na_ans 
    BEGIN
        SET @Final = 'No'
    END

    ELSE IF na_ans > yes_ans AND na_ans > no_ans 
    BEGIN
        SET @Final = 'N/A'
    END

RETURN @Final

END
13
salim
ALTER FUNCTION [dbo].[fnTally] (@SchoolId nvarchar(50))
    RETURNS nvarchar(3)
AS BEGIN 

    DECLARE @Final nvarchar(3)
    SELECT @Final = CASE 
        WHEN yes_ans > no_ans  AND yes_ans > na_ans THEN 'Yes'
        WHEN no_ans  > yes_ans AND no_ans  > na_ans THEN 'No'
        WHEN na_ans  > yes_ans AND na_ans  > no_ans THEN 'N/A' END
    FROM dbo.qrc_maintally
    WHERE school_id = @SchoolId

Return @Final
End

Comme vous pouvez le constater, cela simplifie beaucoup le code. Cela rend également plus évident d'autres erreurs dans votre code: vous retournez un nvarchar, mais vous déclarez que la fonction renvoie un int (corrigé dans le code ci-dessus).

9
Joel Coehoorn

Vous devrez créer des variables locales pour ces colonnes, les affecter lors de la sélection et les utiliser pour vos tests conditionnels.

declare @yes_ans int,
        @no_ans int,
        @na_ans int

SELECT @yes_ans = yes_ans, @no_ans = no_ans, @na_ans = na_ans 
    from dbo.qrc_maintally 
    where school_id = @SchoolId

If @yes_ans > @no_ans and @yes_ans > @na_ans 
begin
Set @Final = 'Yes'
end
-- etc.
7
Joe Stefanelli

Personne ne semble avoir choisi cela si (oui = non)> na ou (non = na)> oui ou (na = oui)> non, vous obtenez NULL comme résultat. Ne croyez pas que c'est ce que vous recherchez.

Voici également une forme plus condensée de la fonction, qui fonctionne même si tout de oui, non ou na_ans est NULL.

USE [***]
GO
/****** Object:  UserDefinedFunction [dbo].[fnActionSq]    Script Date: 02/17/2011 10:21:47 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[fnTally] (@SchoolId nvarchar(50))
RETURNS nvarchar(3)
AS 
BEGIN
return (select (
       select top 1 Result from
       (select 'Yes' Result, yes_ans union all
        select 'No', no_ans union all
        select 'N/A', na_ans) [ ]
        order by yes_ans desc, Result desc)
       from dbo.qrc_maintally
       where school_id = @SchoolId)
End
3
RichardTheKiwi

Je pense que vous seriez mieux avec une déclaration CASE, qui fonctionne beaucoup plus comme IF/ELSEIF

DECLARE @this int, @value varchar(10)
SET @this = 200
SET @value = (
SELECT 
CASE
    WHEN @this between 5 and 10 THEN 'foo'
    WHEN @this between 10 and 15 THEN 'bar'
    WHEN @this < 0 THEN 'barfoo'
    ELSE 'foofoo'
    END
)

Plus d'infos: http://technet.Microsoft.com/en-us/library/ms181765.aspx

2
mpickens
If yes_ans > no_ans and yes_ans > na_ans  

Vous utilisez des noms de colonne dans une instruction (en dehors d'une requête). Si vous voulez des variables, vous devez les déclarer et les affecter.

2
Amy B

Regardez ces lignes:

Si oui_ans> non_ans et oui_ans> na_ans 

et similaire. À quoi les "yes_ans" etc. font-ils référence? Vous ne les utilisez pas dans le contexte d'une requête; la condition "si existe" ne s'étend pas aux noms de colonne que vous utilisez à l'intérieur.

Pensez à affecter ces valeurs à des variables que vous pouvez ensuite utiliser pour votre flux conditionnel ci-dessous. Ainsi,

if exists (some record)
begin
   set @var = column, @var2 = column2, ...

   if (@var1 > @var2)
      -- do something

fin

Le type de retour est également incompatible avec la déclaration. Cela aiderait beaucoup si vous indentiez, utilisiez la ponctuation standard ANSI (terminez les instructions avec des points-virgules) et omettez les débuts/fins superflus - vous n'en avez pas besoin pour les lignes à instruction unique exécutées à la suite d'un test.

0
pelazem