2013-05-01 152 views
0

我在下面的项目上遇到错误,我不明白为什么。任何人都可以为我阐述一些启示吗?IN子句中的逗号分隔值case case语句错误

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 

如果我试图调用这个函数,那么它对一个整数,但对varchars不起作用。即PRINT @ dbo.fn_AcMonthOrder(8)将返回1不如预期,但PRINT @ dbo.fn_AcMonthOrder( '月')或打印@ 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) 

你混合intvarchar。由于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

谢谢你标记数据类型的优先顺序 - 我设法设置这个,只是通过搞乱 - 但我会在后面深入研究。 – 2013-05-01 07:53:18

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答案有更多详细信息(有关数据类型的优先级和优化) – 2013-05-01 07:55:15

1

当您使用IN子句,你应该使用一个数据类型,现在您正在使用“八月”附近,并假定它应该将“月”,......为int它是不正确。 你可以这样写(做它所有你案例Whens)

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