Varchar-to-Datetime转换错误 - 在SELECT中很好但在WHERE中断

时间:2016-08-12 10:45:28

标签: sql-server

我有一个简单的CTE从表中提取日期 - 日期(ApptDateTime)以YYYY-MM-DDZHH:mm:SS格式存储。有些列有NULL值,所以我想忽略它们,以及任何不是真正的日期。

如果我这样做:

;WITH cte
AS
(SELECT
        urn,
        CONVERT(DATETIME, ApptDateTime) AS ApptDateTime

    FROM data
    WHERE ISDATE(ApptDateTime) = 1  
)

SELECT
    *
FROM cte
ORDER BY ApptDateTime

......这很好用;我得到了一份记录清单,按日期排序。但是,如果我只想查看今天之前的日期并引入WHERE

;WITH cte
AS
(SELECT
        urn,
        CONVERT(DATETIME, ApptDateTime) AS ApptDateTime

    FROM data
    WHERE ISDATE(ApptDateTime) = 1  
)

SELECT
    *
FROM cte
WHERE ApptDateTime < GETDATE()
ORDER BY ApptDateTime

我收到错误

  

从字符串转换日期和/或时间时转换失败。

我无法在表格中看到任何狡猾的非日期,非NULL值,即使我有任何不可能CONVERT的内容编辑导致问题成为CTE中SELECT的一部分。但是,当我试图比较日期时间时,它只会抛出该错误。这看起来很简单,我确定我错过了一些令人眼花缭乱的东西 - 但我无法看到它。

编辑:如果我将结果发送到临时表,然后对其进行比较......它运行正常!

SELECT
    urn,
    convert(datetime,ApptDateTime) as ApptDateTime
    into #temp FROM data
    WHERE ISDATE(ApptDateTime) = 1  


SELECT
    *
FROM #temp
WHERE ApptDateTime < getdate()
ORDER BY ApptDateTime

DROP TABLE #temp

1 个答案:

答案 0 :(得分:1)

尝试添加以下条件:WHERE (CASE WHEN ISDATE(ApptDateTime) = 1 THEN ApptDateTime ELSE NULL END) < GETDATE()
我在几天之前遇到了同样的问题,并通过添加CASE来解决。 不清楚SQL如何执行条件。 我还需要找到相同的实际原因。如果我找到任何内容,我会在同一个帖子中发帖。

编辑:如果您在实际查询的执行计划中看到,它将显示ApptDateTime&lt;在ISDATE(ApptDateTime)= 1之前的GETDATE()导致错误。


原因是WHERE子句不遵循短路规则。参考:Is the SQL WHERE clause short-circuit evaluated?