CASE THEN 子句总是被评估
Posted
技术标签:
【中文标题】CASE THEN 子句总是被评估【英文标题】:CASE THEN clause always evaluated 【发布时间】:2012-08-10 09:01:09 【问题描述】:我正在做一个 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 表达式之前。
我不确定这是否相关,但语言对于非本地人来说有些沉重,所以也许是这样?
【问题讨论】:
在将varchar
隐式转换回varchar
时,将其显式转换为money
的唯一目的是,出于格式化目的,为什么不将其存储在所需的格式中开始还是让客户处理格式?
源数据不在我的控制之下。在实际情况下,我必须跳很多圈才能将数据转换成这样一种格式,以便我可以将其插入到它所指定的报告表中(正确键入)
【参考方案1】:
看看下面Use caution when Using CONVERT() with CASE or IF functions in Transact SQL (T-SQL)
最初的想法一般是以下一种“自从第一次 评估的值是数字,它被转换为十进制,所有其他 数据也应该是小数”或“如果 SQL Server 能够 将任何值转换为指定类型,然后所有值都是 预计是转换后的类型”。但是,这是不正确的 (虽然第二个很接近)!
真正的问题是,如果您选择在任何地方转换值 在 Case 语句中,您正在转换值的数据类型 to 是所有值的预期类型,无论它们是否属于 那个类型与否。此外,即使 NONE 的值实际上可以是 已转换(即使 Convert 代码行从未执行),所有 这些值仍应为指定的类型 转换函数!
【讨论】:
谢谢,这说明了原因,但真的没有办法了吗?【参考方案2】:要明确发生了什么,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
【讨论】:
以上是关于CASE THEN 子句总是被评估的主要内容,如果未能解决你的问题,请参考以下文章