SQL Server CASE 表达式未按预期计算
Posted
技术标签:
【中文标题】SQL Server CASE 表达式未按预期计算【英文标题】:SQL Server CASE expression not evaluating as expected 【发布时间】:2018-08-05 12:58:23 【问题描述】:我怀疑我不理解 CASE 表达式的计算方式。
当我运行这个语句时,我得到:
消息 242,第 16 级,状态 3,第 7 行 将 nvarchar 数据类型转换为 datetime 数据类型导致值超出范围。
我明白了;但是,我不确定为什么。在CASE
表达式中,WHEN 1
应该被计算并且没有CAST
应该发生。
我是否误解了CASE
的工作原理?
DECLARE @parameterID int = 42;
DECLARE @userID int = 3;
DECLARE @administratorID int = 2;
--parameterid of 42 has a parametertype of 1
With Param AS
(
SELECT
ParameterValue, USER_ID, P.PARAMETERTYPE_ID AS ParameterType
FROM
dbo.ParameterValues PV
INNER JOIN
Parameters P on P.ID = PV.PARAMETER_ID
WHERE
PARAMETER_ID = @parameterID AND USER_ID = @userID
UNION ALL
SELECT
ParameterValue, USER_ID, P.PARAMETERTYPE_ID AS ParameterType
FROM
dbo.ParameterValues PV
INNER JOIN
Parameters P on P.ID = PV.PARAMETER_ID
WHERE
PARAMETER_ID = @parameterID AND USER_ID = @administratorID
)
SELECT TOP 1
TypedParmValue =
CASE P1.ParameterType
WHEN 1 THEN P1.ParameterValue
WHEN 2 THEN CAST(P1.ParameterValue AS datetime)
WHEN 3 THEN CAST(P1.ParameterValue AS DECIMAL(20,6))
WHEN 4 THEN CAST(P1.ParameterValue as bit)
ELSE P1.ParameterValue
END,
P1.ParameterType,
P1.ParameterValue,
PT.ParameterTypeName
FROM
Param P1
INNER JOIN
ParameterTypes PT on P1.ParameterType = PT.ID
ORDER BY
USER_ID DESC
从功能上讲,我要做的是查找一个参数(值“一般”存储为 nvarchar),然后根据类型(存储在 parametertype 中)将其转换为正确的数据类型。 CTE 用于查找用户特定的参数值或回退到默认值。我知道处理默认参数有不同/更好的方法。
【问题讨论】:
【参考方案1】:是的,您误解了CASE
的工作原理。
首先,它是一个表达式(如a+b
)——而不是一个语句。
因此,CASE
必须返回一个原子值(来自多种可能性) - 所有这些返回值都必须属于同一数据类型。
在您的情况下 - 完全不是这种情况;在这种情况下,SQL Server 将选择data type precedence list 上最高的数据类型——这里是DATETIME
。
因此,将尝试将返回的所有值转换为DATETIME
- 如果WHEN 1
的P1.ParameterValue
不是有效的DATETIME
,则会发生此错误。
【讨论】:
所以,如果我理解正确,我正在尝试做的事情,不能以这种方式完成。或许,与其尝试在 SQL 中执行此操作,不如将参数值和参数类型传回管理器,让 C# 代码执行数据类型转换。 ***.com/questions/24770739/… - 这也提供了很好的解释。 没错 -CASE
表达式只能返回 一种数据类型 - 根据返回的可能值,这些值需要转换为 SQL Server 运行时的任何数据类型作为该表达式的“返回类型”。以上是关于SQL Server CASE 表达式未按预期计算的主要内容,如果未能解决你的问题,请参考以下文章
在 sql server 中未按预期实现使用 round 函数的截断