我无法理解它。我们有以下简单查询。
DECLARE @bFlag bit
SET @bFlag = 0
SELECT something = CASE
WHEN @bFlag = 1 THEN
CASE
WHEN RS.intInterval = 1 THEN '"Days"'
WHEN RS.intInterval = 2 THEN '"Weeks"'
WHEN RS.intInterval = 3 THEN '"Months"'
WHEN RS.intInterval = 4 THEN '"Years"'
END
Else
RS.intInterval
End
from MyTable AS RS WITH (NOLOCK)
所以如果intInterval
未设置为int
,我想获得flag
(true
}。否则,如果flag
设置为true
,我希望获得Days
,Weeks
等,具体取决于intInterval
的值。如果我使用@bFalg = 1
运行此操作,则会收到此错误:
将varchar值'“Weeks”'转换为数据时转换失败 输入int
这没有任何意义,因为我没有转换任何东西。
我知道我可以通过将cast (intInterval as varchar)
放入else
部分来解决问题。但是,我想知道我收到此错误的原因,为什么case
正在尝试将“周”转换为int
?
答案 0 :(得分:12)
使用CASE
语句时,所有结果表达式必须具有相同的数据类型。如果不是,则结果将转换为具有更高优先级的数据类型。根据{{3}}:
从中输入类型集中的最高优先级类型 result_expressions和可选的else_result_expression。
由于INT
的{{3}}高于VARCHAR
,"Weeks"
会转换为INT
并产生错误:
将varchar值'“Weeks”'转换为数据时转换失败 输入int
另一个产生相同错误的例子:
SELECT CASE WHEN 1 = 1 THEN 'True' ELSE 0 END
解决方案是将RS.intInterval
转换为VARCHAR
:
CONVERT(VARCHAR(10), RS.intInterval)
您的最终查询应该是:
DECLARE @bFlag bit
SET @bFlag = 0
SELECT something = CASE
WHEN @bFlag = 1 THEN
CASE
WHEN RS.intInterval = 1 THEN '"Days"'
WHEN RS.intInterval = 2 THEN '"Weeks"'
WHEN RS.intInterval = 3 THEN '"Months"'
WHEN RS.intInterval = 4 THEN '"Years"'
END
Else
CONVERT(VARCHAR(10), RS.intInterval)
End
from MyTable AS RS WITH (NOLOCK)