这样,那么从句始终评估(CASE THEN clause always evaluated)

2019-07-30 21:36发布

我在做一个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语句接收表达作为其输入的结果之前表达式。 在评估这些表述错误是可能的。 出现在当争吵到CASE语句首先计算聚合表达式,然后提供给CASE语句。 例如,以下查询零错误产生MAX聚合的值时产生分频。 这发生之前评估CASE表达式。

我不知道这是相关的,但语言是有点重了非本地的,所以也许它是什么?

Answer 1:

看一看下面用CASE或IF中的Transact SQL(T-SQL)函数使用CONVERT()时要小心

第一个想法通常是一个下面的“自评估的第一个值是数字,将其转换为十进制,和所有其他数据预计将是一个小数,以及” OR“如果SQL Server能够转换的任何值为指定的类型,则所有值预计是经转换的类型”的。 然而,这不是正确的(虽然第二接近)!

真正的问题是,如果你选择在Case语句中的任何位置转换的值,该数据类型要转换的值是所有值的预期类型,不管它们是该类型与否。 此外,即使值都不能真正转化(即使代码转换线从未执行),所有值仍有望被转换函数指定的类型!



Answer 2:

要清楚发生了什么then子句正在评估。

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

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

对于文档CASE解释说,返回类型

返回从类型集合最高的优先级类型result_expressions和可选else_result_expression 。 欲了解更多信息,请参阅数据类型优先级(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


文章来源: CASE THEN clause always evaluated