始终评估CASE THEN子句

时间:2012-08-10 09:01:10

标签: sql sql-server formatting sql-server-2008-r2

我正在使用SELECT使用CASE将nvarchar值转换为正确的类型,如下所示:

SELECT CASE 
    WHEN @propType = 'money' THEN convert(money, datavalue)
    [...]
    ELSE datavalue
END
FROM [...]

但是,即使convert 等于金钱,似乎始终会执行@propType。可运行的例子:

declare @proptype nvarchar(50)= 'nvarchar'
declare @val nvarchar(10) = 'test'
select 
    case @proptype
        when 'money' then convert(money, @val)
        else @val
    end

为什么会这样,我该如何解决这个问题? MSDN文档说明了这一点:

  

CASE语句按顺序评估其条件并停止   条件满足的第一个条件。在一些   在CASE语句之前,会计算表达式   接收表达式的结果作为其输入。错误   评估这些表达式是可能的。聚合表达式   出现在WHEN首先评估CASE语句的参数   提供给CASE声明。例如,以下查询   在产生MAX的值时产生除零误差   骨料。这在评估CASE表达式之前发生。

我不确定这是否相关,但对于非本地语言来说语言有点沉重,所以可能是这样?

2 个答案:

答案 0 :(得分:3)

查看以下Use caution when Using CONVERT() with CASE or IF functions in Transact SQL (T-SQL)

  

第一个想法通常是以下之一“从第一个开始   value的值是numeric,它被转换为decimal,以及所有其他值   数据预计也是小数以及“OR”如果SQL Server能够   将任何值转换为指定的类型,然后所有值都是   预计将是转换类型“。但是,这是不正确的   (虽然第二个很接近)!

     

真正的问题是,如果您选择在任何地方转换值   在Case语句中,您要转换值的数据类型   to是所有值的预期类型,无论它们是否为   那种类型与否。此外,即使值实际上没有   转换(即使转换代码行永远不会执行),所有   这些值仍然应该是由指定的类型   转换功能!

答案 1 :(得分:1)

要明确发生的事情then条款正在评估。

如果你这样做,你会看到同样的错误

SELECT CASE @proptype
         WHEN 'money' THEN $1.0 /*<-- Literal of datatype money*/
         ELSE @val
       END 

CASE的文档解释了返回类型

  

从中输入类型集中的最高优先级类型   result_expressions和可选的else_result_expression。更多   信息,请参阅Data Type Precedence (Transact-SQL)

money的数据类型优先级高于nvarchar,因此评估else @val,然后将其转换为money并失败。

一种可能的解决方法是将其转换为sql_variant,因为它具有比两者更高的数据优先级。

declare @proptype nvarchar(50)= 'nvarchar'
declare @val nvarchar(10) = 'test'
select 
    case @proptype
        when 'money' then convert(money, @val)
        else cast(@val as SQL_VARIANT)
    end