DateValue函数的标准表达式中的数据类型不匹配

时间:2013-02-26 15:28:10

标签: sql ms-access datetime

我有一个基于日期字段选择的查询。问题是这个日期字段有时是null,所以只使用'而不是null'检查null将不起作用。

这是我开发的内容:

SELECT DISTINCT WS_ALL_OBJ.[Owner ID], Users.CHARGE_UNIT, WS_ALL_OBJ.[Owner Name]
FROM WS_ALL_OBJ LEFT JOIN Users ON WS_ALL_OBJ.[Owner ID] = Users.CNAME
WHERE 
    (IIF(IsNull(WS_ALL_OBJ.[Last Modified]), DateValue('2050-12-01'), DateValue(Left(WS_ALL_OBJ.[Last Modified], 10))) < #2012-11-26#
   And 
    (Users.CHARGE_UNIT <> 'CQ'))
GROUP BY WS_ALL_OBJ.[Owner ID], Users.CHARGE_UNIT, WS_ALL_OBJ.[Owner Name];

运行此查询时,会抛出“标准表达式中的数据类型不匹配”错误消息。

我已将其缩小到这行代码 - DateValue(Left(WS_ALL_OBJ.[Last Modified], 10)),因为如果我替换它 - DateValue('2011-11-26') - 它就可以了。

起初我以为是因为我的Last Modified字段中存在空值,这就是我提出这个问题的原因 - (IIF(IsNull(WS_ALL_OBJ.[Last Modified]), DateValue('2050-12-01'), DateValue(Left(WS_ALL_OBJ.[Last Modified], 10))) < #2012-11-26#

不应该解决空值问题吗?

另一种可能性是来自Left()的字符串格式不正确。我认为这是因为 - DateValue('2011-11026') - (格式错误)也会导致数据类型不匹配异常。

然而,这就是所有数据的样子:

2008-01-18 13:10:54 CST

它存储为“文本”字段,来自链接的csv文件。 Left()函数应该取前10个字符并传递给DateValue()

我感到茫然,感谢任何帮助。

更新:我也尝试过cdate(Left(WS_ALL_OBJ.[Last Modified], 10))并收到同样的错误。 我还修改了以`(IsNull(WS_ALL_OBJ。[Last Modified])或WS_ALL_OBJ检查空字符串。[Last Modified] ='')

我最终运行了一些查询,以确保不存在WS_ALL_OBJ.[Last Modified] = ''WS_ALL_OBJ.[Last Modified] = ' '等。他们都返回零结果。

我也尝试了下面建议的查询结构,但无济于事。

2 个答案:

答案 0 :(得分:1)

考虑使用子查询来排除WS_ALL_OBJ为空的[Last Modified]行。这样就可以避免在尝试将Null转换为日期/时间值时发生的错误。

SELECT
    w.[Owner ID], u.CHARGE_UNIT, w.[Owner Name]
FROM
    (
        SELECT [Owner ID], [Owner Name], [Last Modified]
        FROM WS_ALL_OBJ
        WHERE [Last Modified] Is Not Null
    ) AS w
    LEFT JOIN Users AS u
    ON w.[Owner ID] = u.CNAME
WHERE 
        DateValue(Left(w.[Last Modified], 10)) < #2012-11-26#
    AND u.CHARGE_UNIT <> 'CQ'
GROUP BY w.[Owner ID], u.CHARGE_UNIT, w.[Owner Name];

注意:

  1. 我使用别名作为表名,因为这使我的大脑更容易消化SQL。
  2. 由于这是GROUP BY查询,因此不需要DISTINCT
  3. WHERE子句条件(u.CHARGE_UNIT <> 'CQ')违背了LEFT JOIN的目的。我不知道打算发生什么,但在我看来你也可以改用INNER JOIN
  4. 如果[Last Modified]也可能包含零长度字符串,请在子查询WHERE中排除它们:

    在哪里Len([上次修改])&gt; 0

  5. 或者只是使用IsDate()

    WHERE IsDate([Last Modified]) = True
    

    或......

    WHERE IsDate(Left([Last Modified]), 10) = True
    
    顺便说一下,您可能已经注意到[Last Modified]作为日期/时间而不是文本数据类型会更容易。我假设你出于某种原因陷入了困境。但是,如果没有,请考虑改变它。

答案 1 :(得分:0)

以下是我通常如何处理这个问题。我冒昧地使用别名来缩短SQL并使其更具可读性。我强烈建议您不要在字段名称中使用空格。如果你停止练习,你就不必担心使用括号。

我也猜测你将日期值存储为字符串。我一般都试图避免这种情况。我认为在大多数情况下,最好在需要时将日期值转换为字符串,而不是相反。

确保将vDate参数保留在下面的函数中作为变量数据类型。如果将其更改为字符串或日期,则不允许您处理空值。而不是出错,你的SQL会产生非常奇怪的结果。

您确定日期总是10个字符吗?日期值可以表示为没有前导零,这使得它们更短。

SELECT DISTINCT w.[Owner ID], u.CHARGE_UNIT, w.[Owner Name]
FROM WS_ALL_OBJ as w LEFT JOIN Users as u ON w.[Owner ID] = u.CNAME
WHERE 
    GetLastModDate(w.[Last Modified]) < #2012-11-26#
   And 
    u.CHARGE_UNIT <> 'CQ'
GROUP BY w.[Owner ID], u.CHARGE_UNIT, w.[Owner Name];


'Put this code in a VBA Module
Public Function GetLastModDate(vDate) as Date
    If Nz(vDate, "") = "" Then
        GetLastModDate = #01/12/2050#
    Else
        GetLastModDate = DateValue(Left(vDate), 10)
        End If
End Function