Если иначе, если в функции сервера SQL - PullRequest
13 голосов
/ 17 февраля 2011

У меня есть эта функция, которую я пытаюсь создать.Когда я анализирую его, он работает нормально, но для создания функции в базе данных он говорит, что имена моих столбцов недействительны.Это неправда, я правильно их написал.Вот код:

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

Ответы [ 6 ]

9 голосов
/ 17 февраля 2011
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

Как видите, это сильно упрощает код.Это также делает другие ошибки в вашем коде более очевидными: вы возвращаете nvarchar, но объявили функцию, возвращающую int (исправлено в приведенном выше коде).

7 голосов
/ 17 февраля 2011

Вам нужно будет создать локальные переменные для этих столбцов, назначить их во время выбора и использовать их для ваших условных тестов.

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.
3 голосов
/ 17 февраля 2011

Никто, кажется, не заметил, что если (да = нет)> нет или (нет = нет)> да или (нет = да)> нет, в результате вы получите NULL.Не верьте, что это то, что вам нужно.

Вот также более сжатая форма функции, которая работает , даже если любой из yes, no или na_ans равен 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
2 голосов
/ 20 августа 2013

Я думаю, вам лучше использовать оператор CASE, который работает намного больше, чем 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
)

Дополнительная информация: http://technet.microsoft.com/en-us/library/ms181765.aspx

2 голосов
/ 17 февраля 2011
If yes_ans > no_ans and yes_ans > na_ans  

Вы используете имена столбцов в выражении (вне запроса).Если вам нужны переменные, вы должны объявить и назначить их.

0 голосов
/ 17 февраля 2011

Посмотрите на эти строки:

Если yes_ans> no_ans и yes_ans> na_ans

и аналогичные.К чему относятся «yes_ans» и т. Д.?Вы не используете их в контексте запроса;условие «если существует» не распространяется на имена столбцов, которые вы используете внутри.

Рассмотрите возможность присвоения этих значений переменным, которые затем можно использовать для условного потока ниже.Таким образом,

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

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

end

Тип возвращаемого значения также не соответствует объявлению.Было бы очень полезно, если бы вы использовали отступы, использовали стандартную пунктуацию ANSI (завершите операторы точками с запятой) и пропустили лишние начало / конец - они вам не нужны для строк с одним оператором, выполняемых в результате теста.*

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...