IN子句中的逗号分隔值case case语句错误
我在下面的项目上遇到错误,我不明白为什么。任何人都可以为我阐述一些启示吗?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.
当您在表达式中使用不同的数据类型,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
^^^^^
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()子句要求其中的值必须兼容其中的数据类型转换。
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
谢谢Scoregraphic - 这并修复错误,但是我觉得从andomar答案有更多详细信息(有关数据类型的优先级和优化) – 2013-05-01 07:55:15
当您使用IN子句,你应该使用一个数据类型,现在您正在使用“八月”附近,并假定它应该将“月”,......为int它是不正确。 你可以这样写(做它所有你案例Whens)
WHEN @Month IN ('Aug','August','8') THEN 1
.....
谢谢你标记数据类型的优先顺序 - 我设法设置这个,只是通过搞乱 - 但我会在后面深入研究。 – 2013-05-01 07:53:18