【问题标题】:SQL: Error when trying to filter out all dates older than the current dateSQL:尝试过滤掉所有早于当前日期的日期时出错
【发布时间】:2012-02-08 21:45:35
【问题描述】:

我使用的是 SQL SERVER 2008。 我有一个以日期时间格式存储日期的表格(即2012-01-21 15:00:00.000

我正在尝试过滤掉所有早于“今天”的日期。所以我试图通过使用下面的查询来做到这一点。

SELECT Date
  FROM MyTable
 WHERE Date >= GETDATE()

当我运行它时,我得到了以下错误。

Conversion failed when converting date and/or time from character string.

我做错了什么吗?感谢您的帮助,如果我需要提供更多信息,请告诉我!

更多信息:

[Date] 是 MyTable 中的 DateTime 类型。

我还有一个视图,它只选择 [日期] 并且不进行任何操作

我正在通过视图访问 [日期]

【问题讨论】:

  • 您的表格中Date 列的类型是什么?
  • 听起来 Date 列是 VARCHAR/NVARCHAR 而不是 DATETIME。因此,虽然日期/时间可以像日期时间一样格式化,但就架构而言,它们并没有被存储为一个。你能确认一下数据库架构吗?
  • 我检查了我的日期列的数据类型,它显示“日期时间”,但是我正在查询一个视图,该视图部分包含在该表中。那么当通过我的视图访问时,DataType 会丢失吗?
  • 这取决于视图如何提取数据。除非视图正在操作数据,否则数据类型不应丢失。
  • @Chris J,对于 Date 部分,它只是从表中选择日期.. SELECT D.[Date] FROM dbo.MyTable

标签: sql sql-server-2008 datetime date


【解决方案1】:

看来您的列毕竟不是DATETIME 数据类型。它可能是VARCHAR 或类似的。如果您提供用于创建表的 DDL,则可以提供更具体的答案。

【讨论】:

  • 我使用了 ISDATE(Date) 但我猜即使它是 varchar 只要格式正确,它也会返回 True?
  • 理想情况下,您可以将表中的数据类型更改为 DATETIME 或类似的。
  • 正确:从网上的sql书籍中截取...“下面的例子展示了如何使用ISDATE来测试一个字符串是否是一个有效的日期时间。”
  • @daveomcd 我只是在我的回答中提出这个建议。来自msdn.microsoft.com/en-us/library/ms187347.aspx - 仅当您将 ISDATE 与 CONVERT 函数一起使用时,如果指定了 CONVERT 样式参数,并且样式不等于 0、100、9 或 109,ISDATE 才是确定性的。跨度>
  • @daveomcd - 是的,IsDate() 专门用于检查字符串,而不是日期:)
【解决方案2】:

您不必说您所在的区域设置,因为这很重要。最可能的可能性是您的 DATE 列不是 DATETIME。您没有说明您的语言环境,但(例如)美国和英国的日期时间格式在反向格式时会受到不同的处理。

英国将日期视为yyyy-dd-mm hh:mm:ss.fff
美国将日期视为yyyy-mm-dd hh:mm:ss.fff

例如,这会引发错误:

SET LANGUAGE british
GO
SELECT CAST ('1999-01-21 10:11:12.345' AS DATETIME)
GO

但是,如果您将语言环境更改为 us_english,它将正确解析。

如果你想保证它总是被解析为yyyy-mm-dd,那么你需要严格并通过在日期和时间之间指定Z来使用完整的ISO规范,例如:1999-01-21Z10:11:12.345将解析在两种语言环境中以相同的方式。

最终,您希望将Date 列更改为DATETIME 的数据类型,但您可能需要临时更改您的语言环境才能成功执行此操作;即:

SET LANGUAGE us_english
GO
ALTER TABLE [...]
GO
SET LANGUAGE british
GO

在处理日期/时间数据时要注意另一个有趣的“陷阱”。

旁注:不,我不知道为什么微软认为我们在 Blighty 中将日期视为 yyyy-dd-mm ...我从未遇到过这种格式。可以从欧洲格式继承吗?

【讨论】:

    【解决方案3】:

    首先你应该把它改成:

    SELECT [Date]
      FROM MyTable
     WHERE [Date] <= GETDATE()
    

    那种类型的Column是[Date]????

    【讨论】:

      【解决方案4】:

      如果您的日期列是VARCHAR/NVARCHAR,您需要将该值转换为DATETIME。从您的示例中,正确的格式应该是:

      SELECT [Date]
        FROM MyTable
       WHERE CONVERT(DATETIME,[Date],121) >= GETDATE()
      

      【讨论】:

        【解决方案5】:

        如果您将 varchar 与日期时间进行比较,SQL 将隐式将其转换为数据时间。您遇到的问题是您的表中有一条不是日期时间格式的记录。

        好例子:

        SELECT *
        INTO #Temp
        FROM
        (
            SELECT '2010-01-21 15:00:00.000' [Date] UNION
            SELECT '2012-01-21 05:30:00.000' [Date] UNION
            SELECT '2015-01-21 07:45:00.000' [Date] UNION
            SELECT '2020-01-21 11:20:00.000' [Date]
        ) x
        
        SELECT *
        FROM #Temp
        WHERE [Date] > GETDATE()
        
        DROP TABLE #Temp
        

        破例:

        SELECT *
        INTO #Temp
        FROM
        (
            SELECT '2010-01-21 15:00:00.000' [Date] UNION
            SELECT '2012-01-21 05:30:00.000' [Date] UNION
            SELECT '2015-01-21 07:45:00.000' [Date] UNION
            SELECT 'a2020-01-21 11:20:00.000' [Date]
        ) x
        
        SELECT *
        FROM #Temp
        WHERE [Date] > GETDATE()
        
        DROP TABLE #Temp
        

        损坏示例的最后一条记录中的“a”将导致您得到的错误。

        解决方法

        SELECT *
        INTO #Temp
        FROM
        (
            SELECT '2010-01-21 15:00:00.000' [Date] UNION
            SELECT '2012-01-21 05:30:00.000' [Date] UNION
            SELECT '2015-01-21 07:45:00.000' [Date] UNION
            SELECT 'a2020-01-21 11:20:00.000' [Date]
        ) x
        
        SELECT *
        FROM
        (
            SELECT CASE WHEN ISDATE([Date]) = 1 THEN [Date] ELSE '' END [Date]
            FROM #Temp
        ) x
        WHERE [Date] > GETDATE()
        
        DROP TABLE #Temp
        

        更好的选择

        SELECT *
        INTO #Temp
        FROM
        (
            SELECT '2010-01-21 15:00:00.000' [Date] UNION
            SELECT '2012-01-21 05:30:00.000' [Date] UNION
            SELECT '2015-01-21 07:45:00.000' [Date] UNION
            SELECT 'a2020-01-21 11:20:00.000' [Date]
        ) x
        
        SELECT *
        FROM #Temp
        WHERE CASE WHEN ISDATE([Date]) = 1 THEN [Date] ELSE '' END > GETDATE()
        
        DROP TABLE #Temp
        

        【讨论】:

        • 我可以在 WHERE 子句中添加一些内容来忽略那些不属于正确类型的内容吗?
        • @daveomcd 我添加了一个解决方法。唯一的问题是,如果您要选择更多记录,则必须将它们添加到嵌套选择中。 Case 语句应该过滤掉不良记录。
        • @daveomcd 我添加了一个更好的选择。这将允许您仍然使用 * 获取表中的所有其他记录,但能够过滤 [Date] 字段。
        • 好的,我正要看看。我注意到实际上它必须通过另一个视图,我猜你会称它为派生表? (即...... FROM(SELECT [DATE] FROM VIEW))所以也许这会导致它丢失它的数据类型。感谢所有示例!
        猜你喜欢
        • 2013-02-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-30
        • 2014-02-19
        • 2013-02-09
        • 2011-04-05
        相关资源
        最近更新 更多