问题描述
使用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
它的选择取决于执行计划。