在 case 语句中转换 varchar 值时转换失败

Conversion failed when converting the varchar value in case statement

我无法理解它。我们有以下简单查询。

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)

所以如果flag没有设置为true,我想得到intInterval(即int)。否则,如果 flag 设置为 true,我想根据 intInterval 的值获得 DaysWeeks 等。如果我用 @bFalg = 1 运行 这个,我得到这个错误:

Conversion failed when converting the varchar value '"Weeks"' to data type int

这没有任何意义,因为我没有转换任何东西。

我知道我可以通过将 cast (intInterval as varchar) 放在 else 部分来修复它。但是我想知道我收到此错误的原因,为什么 case 试图将 'Weeks' 转换为 int

使用CASE语句时,所有结果表达式必须具有相同的数据类型。如果不是,则结果将转换为具有更高优先级的数据类型。根据 BOL:

Returns the highest precedence type from the set of types in result_expressions and the optional else_result_expression.

由于 INTdata type precedence 高于 VARCHAR"Weeks" 被转换为 INT 并产生错误:

Conversion failed when converting the varchar value '"Weeks"' to data type 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)