5

我正在做一个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 语句的 WHEN 参数中的聚合表达式,然后将其提供给 CASE 语句。例如,以下查询在生成 MAX 聚合的值时会产生除以零错误。这发生在评估 CASE 表达式之前。

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

4

2 回答 2

3

请查看以下内容在 Transact SQL (T-SQL) 中将 CONVERT() 与 CASE 或 IF 函数一起使用时要小心

第一个想法通常是以下之一“由于评估的第一个值是数字,因此将其转换为十进制,并且所有其他数据也应为十进制”或“如果 SQL Server 能够转换任何值到指定的类型,那么所有值都应该是转换后的类型”。但是,这是不正确的(尽管第二个很接近)!

真正的问题是,如果您选择在 Case 语句中的任何位置转换值,则您将值转换为的数据类型是所有值的预期类型,无论它们是否属于该类型。此外,即使 NONE 值实际上可以转换(即使 Convert 代码行从不执行),所有值仍应为 Convert 函数指定的类型!

于 2012-08-10T09:13:08.143 回答
1

要清楚正在发生的事情,该then子句没有被评估。

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

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

的文档CASE解释了返回类型

result_expressions从 in和可选的类型集中返回最高优先级的类型 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
于 2013-10-18T16:43:19.630 回答