2013-05-01 4 views
0

Я столкнулся с ошибкой в ​​приведенном ниже пункте, и я не понимаю, почему. Может ли кто-нибудь пролить свет на него для меня?Значение, разделенное запятой SQL в IN, условие case case error

CREATE FUNCTION dbo.fn_AcMonthOrder 
(
    @Month varchar(100) 
) 
RETURNS INT 
AS 
BEGIN 
    DECLARE @MonthOrder Int 
    SET @MonthOrder = 
     (CASE 
     WHEN @Month IN ('Aug','August',8) THEN 1 
     WHEN @Month IN ('Sep','September',9) THEN 2 
     [email protected] IN ('Oct','October',10) THEN 3 
     ... 
     ELSE 0 END) 
    RETURN @MonthOrder 
END 

Если я пытаюсь вызвать эту функцию, то она отлично работает на целое число, но не для типа VARCHAR. То есть PRINT @ dbo.fn_AcMonthOrder (8) возвращает 1, как и ожидалось, но PRINT @ dbo.fn_AcMonthOrder ('Август') Или PRINT @ dbo.fn_AcMonthOrder ('Август') возвращает следующее сообщение об ошибке:

Msg 245, Level 16, State 1, Line 1 
Conversion failed when converting the varchar value 'Aug' to data type int. 

ответ

2

При использовании различных типов данных в выражении SQL Server следует data type precedence. В этом случае:

8 IN ('Aug','August', 8) 

Вы смешивания int с varchar. Поскольку int имеет более высокий приоритет, он преобразует varchar в int. Причина, по которой этот конкретный случай не вызывает ошибку, может быть оптимизацией. Это делает сгенерирует ошибку:

8 IN ('Aug','August',10) 

И это не бросает ошибку:

'Aug' IN ('Aug','August',8) 

Но это опять-таки выдает ошибку:

'Sept' IN ('Aug','August',8) 

Это подтверждает, что оптимизатор первым сравнивает элементы, которые не требуют преобразования. Он вызывает только ошибку, когда попадает в элементы, которые он не может преобразовать.

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

WHEN @Month IN ('Aug','August','8') THEN 1 
           ^^^^^ 
+0

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

1
 WHEN @Month IN ('Aug','August','8') THEN 1 
     WHEN @Month IN ('Sep','September','9') THEN 2 
     [email protected] IN ('Oct','October','10') THEN 3 

Включить в одиночные кавычки значения месяца в цифрах, например, изменить 8 на '8'. Это связано с тем, что @Month имеет тип данных VARCHAR(), а предложение IN() требует, чтобы значения внутри него должны иметь совместимое преобразование типов данных среди них.

1

Все элементы в IN-списке должны быть типа, где возможно неявное преобразование. Вы не можете преобразовать значение varchar в целочисленное, но наоборот. Поэтому попробуйте это утверждение.

CREATE FUNCTION dbo.fn_AcMonthOrder 
(
    @Month varchar(100) 
) 
RETURNS INT AS 
BEGIN 
    DECLARE @MonthOrder Int 
    SET @MonthOrder = 
    (CASE 
     WHEN @Month IN ('Aug','August','8') THEN 1 
     WHEN @Month IN ('Sep','September','9') THEN 2 
     [email protected] IN ('Oct','October','10') THEN 3 
     ELSE 0 
    END) 
    RETURN @MonthOrder 
END 
+0

Спасибо Scoregraphic - это сделали исправить ошибку, но я чувствовал, что ответ от andomar имеет больше деталей (о типе данных старшинства и оптимизации) –

1

При использовании в пункте вы должны использовать один тип данных в настоящее время используют ваши «Aug» рядом , и предполагает, что он должен преобразовать «» авг ... в целое неверно , вы можете написать его таким образом (Сделайте это для всех вас Case Whens)

WHEN @Month IN ('Aug','August','8') THEN 1 
.....