我正在使用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表达式之前发生。
我不确定这是否相关,但对于非本地语言来说语言有点沉重,所以可能是这样?
答案 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