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
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).
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.
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
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
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.
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.