如何检查输入的日期mm / dd / yyyy而不是dd / mm / yyyy?

时间:2016-03-01 21:20:46

标签: sql datetime ms-access

目标

我在MS Access数据库中工作。我需要确定用户输入错误的DateCollected的情况。具体地说,当用户输入mm / dd / yyyy而不是dd / mm / yyyy时。这些必须在事后发现,因为在入口点没有数据验证。

我有一个引用日期DateEntry,我知道它是正确的,因为它是由数据库加盖时间戳的。我已经确定了验证收集日期的这些方法:

  1. 如果日期> 12,用户不会意外输入dd / mm / yyyy为mm / dd / yyyy。
  2. DateCollected不能在DateEntry之后。收藏总是先发生。
  3. 查看DateCollected和DateEntry之间的差异。如果它超过60天,我怀疑输入不好。为了确认,我将月份和日期反转以创建NewDate,如果重新计算的点差少于60天,我可以对错误进行分类。
  4. 查询

    SELECT [T].[DateCollected], 
    [T].[DateEntry], 
    [T].[DateEntry]-[T].[DateCollected] AS Spread,
    DateSerial(Year([T].[DateCollected]),Day([T].[DateCollected]),Month([T].[DateCollected])) AS NewDate, 
    [T].[DateEntry]-[NewDate] AS NewSpread
    FROM T
    WHERE ((Day([T].[DateCollected])<=12))
    ORDER BY [T].[DateEntry]-[T].[DateCollected] DESC
    

    输出

    | DateCollected |  DateEntry   | Spread |   NewDate   | NewSpread |
    -------------------------------------------------------------------
    |  12/02/2004   |  17/12/2004  |   309  |  02/12/2004 |    15     |
    |  11/02/2009   |  03/12/2009  |   295  |  02/11/2009 |    31     |
    |  12/05/2008   |  19/02/2009  |   283  |  05/12/2008 |    76     |
    |  10/01/2010   |  14/10/2010  |   277  |  01/10/2010 |    13     |
    |  11/12/2007   |  26/06/2008  |   198  |  12/11/2007 |    227    |
    |  03/07/2007   |  20/11/2007  |   140  |  07/03/2007 |    258    |
    |  12/04/2008   |  28/08/2008  |   137  |  04/12/2008 |    -98    |
    |  05/06/2013   |  15/05/2013  |   -21  |  15/05/2013 |     9     |
    |  01/10/2005   |  18/01/2005  |  -256  |  18/01/2005 |     8     |
    

    问题

    我遇到了以这种方式编写查询的麻烦,因为出于某种原因我不能将过滤器应用于NewSpread列。例如,我想过滤掉NewSpread为负数(违反上述规则#2)或NewSpread&gt; Spread(不是由混合mm和dd引起)的任何情况。当我尝试包含过滤器时,例如

    WHERE ((Day([T].[DateCollected])<=12)) AND (([T].[DateEntry]-[NewDate])>0)
    

    我收到一个错误,它要求NewDate的参数值。

    enter image description here

    问题

    如何修复我的查询,以便它允许NewSpread列上的过滤器?

    有没有更好的方法来查找以mm / dd / yyyy而不是dd / mm / yyyy输入的日期?

2 个答案:

答案 0 :(得分:2)

问题是这些表达式必须重复,甚至是[NewDate]的表达式,因为你不能在WHERE子句中使用给定的别名。

但是,如果将查询包装在另一个查询中,则会变得更容易,如下所示:

SELECT *
FROM (
    SELECT   [DateCollected], 
             [DateEntry], 
             DateDiff("d", [DateCollected], [DateEntry]) AS Spread,
             Iif(DateCollected IS NULL, 0, DateSerial(Year([DateCollected]),Day([DateCollected]),Month([DateCollected]))) AS NewDate, 
             DateDiff("d", [NewDate], [DateEntry]) AS NewSpread
    FROM     T
    WHERE    Day([DateCollected]) <= 12
) AS Main
WHERE    [Main].[NewSpread] > 0 
ORDER BY [Main].[Spread] DESC

现在您可以在[NewSpread]上执行WHERE条件。

注意:我很惊讶地看到[DateEntry]-[NewDate] AS NewSpread在内部SELECT中有效,因为已经存在[NewDate]是别名。如果这是一个问题,那么在外部SELECT进行此计算。

对于更复杂的查询,您甚至可能希望将外部查询本身再次包装在另一个包装SELECT中。

使用DateDiff function并计算两个日期之间的天数,可以规避您遇到的数据类型不匹配。

如果您希望该数字包含小数,请使用分钟和除法,例如:

DateDiff("n", [DateCollected], [DateEntry])/60/24 AS Spread

答案 1 :(得分:0)

您应该将parameter定义为date。要执行此操作,请转到设计视图,打开“查询参数”对话框,粘贴[您的参数]的名称并将其数据类型设置为Date。这样,Access将确保它是一个有效的日期。用户可以使用任何有效的日期格式 另外一个好处是,如果您查询SQL Server或Oracle链接表,您可能会看到性能大大提高,因为您的参数现在已正确键入。 这对于2015年7月5日这样的日期不会有帮助,但您可以要求您的用户输入2015年5月7日。