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

时间:2015-08-14 00:38:24

标签: sql-server case

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

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,我想获得flagtrue}。否则,如果flag设置为true,我希望获得DaysWeeks等,具体取决于intInterval的值。如果我使用@bFalg = 1运行此操作,则会收到此错误:

  

将varchar值'“Weeks”'转换为数据时转换失败   输入int

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

我知道我可以通过将cast (intInterval as varchar)放入else部分来解决问题。但是,我想知道我收到此错误的原因,为什么case正在尝试将“周”转换为int

1 个答案:

答案 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)