我在下面的项目上遇到错误,我不明白为什么。任何人都能为我解释一下吗?
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
WHEN@Month IN ('Oct','October',10) THEN 3
...
ELSE 0 END)
RETURN @MonthOrder
END
如果我尝试调用此函数,那么它适用于整数,但不适用于varchars。即PRINT @ dbo.fn_AcMonthOrder(8)将按预期返回1,但PRINT @ dbo.fn_AcMonthOrder('Aug')或PRINT @ dbo.fn_AcMonthOrder('August')将返回以下错误:
Msg 245, Level 16, State 1, Line 1
Conversion failed when converting the varchar value 'Aug' to data type int.
答案 0 :(得分: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
^^^^^
答案 1 :(得分:1)
WHEN @Month IN ('Aug','August','8') THEN 1
WHEN @Month IN ('Sep','September','9') THEN 2
WHEN@Month IN ('Oct','October','10') THEN 3
将单引号月份值包含在数字中,例如将8更改为“8”。 这是因为@Month属于VARCHAR()数据类型,IN()子句要求其中的值必须在它们之间具有兼容的数据类型转换。
答案 2 :(得分: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
WHEN@Month IN ('Oct','October','10') THEN 3
ELSE 0
END)
RETURN @MonthOrder
END
答案 3 :(得分:1)
当你使用IN子句时,你应该使用一个DataType,现在你使用'Aug' 8 附近,它假定它应该转换'aug',... 。到int它是不正确的。 你可以用这种方式写出来(为你们所有人做这件事)
WHEN @Month IN ('Aug','August','8') THEN 1
.....