SQL:尝试筛选出所有早于当前日期的日期时出错

SQL:尝试筛选出所有早于当前日期的日期时出错,sql,sql-server-2008,datetime,date,Sql,Sql Server 2008,Datetime,Date,我正在使用SQLServer2008。 我有一个以日期时间格式存储日期的表(即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.

我正在使用SQLServer2008。 我有一个以日期时间格式存储日期的表(即
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]

看起来您的列毕竟不是
DATETIME
数据类型。它可能是
VARCHAR
或类似的。如果您为表的创建提供DDL,那么将允许更具体的答案。

看起来您的列毕竟不是
DATETIME
数据类型。它可能是
VARCHAR
或类似的。如果您为创建表提供DDL,那么将允许更具体的答案。

首先,您应该将其更改为:

SELECT [Date]
  FROM MyTable
 WHERE [Date] <= GETDATE()
选择[日期]
从MyTable

其中[Date]首先,您应该将其更改为:

SELECT [Date]
  FROM MyTable
 WHERE [Date] <= GETDATE()
选择[日期]
从MyTable

其中,[Date]如果日期列是
VARCHAR/NVARCHAR
,则需要将该值转换为
DATETIME
。根据您的示例,正确的格式应为:

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

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

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

如果将varchar与datetime进行比较,SQL将隐式地将其转换为datatime。您遇到的问题是,表中有一条记录不是datetime格式

好例子:

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

如果将varchar与datetime进行比较,SQL将隐式地将其转换为datatime。您遇到的问题是,表中有一条记录不是datetime格式

好例子:

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

你不能说你的语言环境是什么,因为这将很重要。最有可能的情况是,日期列不是日期时间。您没有说您的语言环境是什么,但是(作为一个例子)美国和英国的日期时间格式在使用反向格式时会得到不同的处理

英国将日期视为
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\u english
,它将正确解析

如果您想保证它总是被解析为
yyyy-mm-dd
,那么您需要严格使用完整的ISO规范,在日期和时间之间指定
Z
,例如:
1999-01-21Z10:11:12.345
将以相同的方式在两个地区进行解析

最后,您希望将
Date
列更改为
DATETIME
的数据类型,但您可能需要临时更改您的区域设置才能成功完成此操作;i、 e:

SET LANGUAGE us_english
GO
ALTER TABLE [...]
GO
SET LANGUAGE british
GO
在处理日期/时间数据时,另一个有趣的“抓住了”要小心


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

您不能说您的语言环境是什么,因为这个将起作用。最有可能的情况是,日期列不是日期时间。您没有说您的语言环境是什么,但是(作为一个例子)美国和英国的日期时间格式在使用反向格式时会得到不同的处理

英国将日期视为
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\u english
,它将正确解析

如果您想保证它总是被解析为
yyyy-mm-dd
,那么您需要严格使用完整的ISO规范,在日期和时间之间指定
Z
,例如:
1999-01-21Z10:11:12.345
将以相同的方式在两个地区进行解析

最后,您希望将
Date
列更改为
DATETIME
的数据类型,但您可能需要临时更改您的区域设置才能成功完成此操作;i、 e:

SET LANGUAGE us_english
GO
ALTER TABLE [...]
GO
SET LANGUAGE british
GO
在处理日期/时间数据时,另一个有趣的“抓住了”要小心


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

表中日期列的类型是什么?听起来日期列是VARCHAR/NVARCHAR而不是DATETIME。因此,尽管日期/时间的格式可能类似于日期时间,但就模式而言,它们并不是存储为一个。你能确认数据库模式吗?我检查了Date列的数据类型,它显示“datetime”,但是我查询的是一个部分来自该表的视图。那么,当通过我的视图访问数据类型时,它会丢失吗?这取决于视图如何提取数据。数据类型不应丢失,除非视图正在处理数据。@Chris J,对于日期部分,它只是从表中选择日期
从dbo.MyTable中选择D.[Date]
表中日期列的类型是什么?听起来日期列是VARCHAR/NVARCHAR而不是DATETIME。因此,虽然日期/时间的格式可能类似于日期时间,但它们并不是一个一个地存储