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 1P1.ParameterValue 不是有效的DATETIME,则会发生此错误。

【讨论】:

所以,如果我理解正确,我正在尝试做的事情,不能以这种方式完成。或许,与其尝试在 SQL 中执行此操作,不如将参数值和参数类型传回管理器,让 C# 代码执行数据类型转换。 ***.com/questions/24770739/… - 这也提供了很好的解释。 没错 - CASE 表达式只能返回 一种数据类型 - 根据返回的可能值,这些值需要转换为 SQL Server 运行时的任何数据类型作为该表达式的“返回类型”。

以上是关于SQL Server CASE 表达式未按预期计算的主要内容,如果未能解决你的问题,请参考以下文章

在 sql server 中未按预期实现使用 round 函数的截断

SQL Server:具有软删除功能的 Graph-DB 未按预期工作

subprocess.call未按预期运行

正则表达式未按预期进行评估

SQL 查询未按预期给出结果

LDAP olcAccess 正则表达式未按预期工作