即使CTE应该只有好的日期也会出现转换错误

问题描述

使用sql Server-我的问题是:尽管CTE仅具有日期良好的行,我怎么仍会出现转换错误

如果我仅使用具有有效日期的行进行CTE ...我仍然会收到错误消息。

WITH goodDates AS
(
    SELECT * 
    FROM impExpRaw2 
    WHERE ISDATE(dateofservice) = 1 
      AND DateofService <> '' 
      AND DateofService IS NOT NULL
)
SELECT * 
FROM goodDates 
WHERE DATEDIFF(d,'7/31/2020',dateofservice) > 0 

这会产生以下错误消息,我希望该字段中有类似“ 2/31/2020”或“ cat”的日期...

第241条消息,第16层,状态1,第293行
字符串转换日期和/或时间时转换失败。

有点沮丧,因为我找不到日期不好的行。

我可以选择一个临时表,然后执行dateDiff,一切正常。 对我来说,这种方法确实可以排除疯狂的数据或带有隐藏的chr(0)或嵌入其中的内容

select * 
into #gd 
from impExpRaw2 
where isdate(dateofservice) = 1   

select * 
from #gd 
where datediff (d,dateofservice) > 0 

这是今天在我的开发机上发生的,但在更新版本上也发生了

感兴趣的人的版本信息

Microsoft sql Server 2016 (RTM-GDR) (KB3164398) - 13.0.1708.0 (X64)   
copyright (c) Microsoft Corporation  
Standard Edition (64-bit) on Windows Server 2012 R2 Standard 6.3 <X64> (Build 9600: ) 

解决方法

我建议使用db而不是try_cast():它更加可靠,因为它实际上是将字符串强制转换为日期,而不是依赖于一些复杂的启发式方法。

您可以将查询的短语设置为:

isdate()
当转换失败时,

select * from impExpRaw2 where try_cast(dateofservice as datetime) >= '20200801' 返回try_cast(),这不满足null谓词。请注意,使用此方法,您无需显式过滤掉where或空值(转换函数将很好地返回null值)。

最后:声明日期文字时,使用格式null是更安全的,无论区域设置如何,SQL Server始终将其识别为日期。

,

鉴于CTE仅具有良好的日期,我怎么仍会遇到转换错误

因为SQL Server优化了整个查询,实际上并没有“首先”运行CTE子查询。 SQL Server是免费的

DATEDIFF(d,'7/31/2020',dateofservice)

在应用任一

之前
ISDATE(dateofservice)=1 

它的选择取决于执行计划。