SQL Server CASE表达式未按预期评估

时间:2018-08-05 12:58:23

标签: sql-server casting case

我怀疑我不了解CASE表达式的计算方式。

运行此语句时,我得到:

  

Msg 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 个答案:

答案 0 :(得分:1)

是的,您误解了private var previousOldestMessageTimestamp: Long = -1 private fun firstFetch(){ //get oldest messages //update previousOldestMessageTimestamp to oldest message timestamp } private fun fetchMore() { val conversationRef = FirebaseFirestore.getInstance() .document("conversations") .collection("some_id") conversationRef .whereLessThan("timestamp", previousOldestMessageTimestamp) //^ 0 messages .orderBy("timestamp", Query.Direction.DESCENDING) .endBefore(previousOldestMessageTimestamp) //^ returns 0 messages .orderBy("timestamp") .endBefore(previousOldestMessageTimestamp) //^ returns messages but starts with oldest one, //not what I want .limit(20) .get().addOnCompleteListener { it: Task<QuerySnapshot!> val messages: List<Message> = it.result.map { it.toObject(Message::class.java) } println("I fetched ${messages.size} messages : $messages") if (messages.isNotEmpty()) { previousOldestMessageTimestamp = *oldestMessage*.timestamp } } } 的工作原理。

首先,它是一个表达式(例如CASE),而不是语句。

因此,a+b必须返回一个原子值(有几种可能)-所有这些返回值都必须具有相同的数据类型

在您的情况下-完全不是这样;在这种情况下,SQL Server将选择data type precedence list上最高的数据类型-这里是CASE

因此,所有返回的所有值都将尝试转换为DATETIME-如果DATETIME的{​​{1}}不是有效的{{1} },就会发生此错误。