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

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

提问人:Nathan Wenger 提问时间:5/11/2023 最后编辑:Joel CoehoornNathan Wenger 更新时间:5/11/2023 访问量:178

问:

早上好。我在以下代码中遇到了上述问题。

SELECT            c.Account_SPID__c [SPID]
                  ,CONVERT(DATE,c.Background_Check_Authorization_Date_Sent__c) [Sent]
                  ,CONVERT(DATE,c.BGC_Completion_Date__c) [Complete]
                  ,c.BGC_Status__c [BGC Status]
                  ,m2.market
                  ,a.billingstate
                  
FROM        SalesForceLocal_Reporting.dbo.Contact c WITH (NOLOCK)

inner join SalesForceLocal.dbo.Account a with (nolock) on c.account_spid__C = a.spid__C
inner join SalesForceLocal.dbo.market__C m with (nolock) on a.market__C = m.id
inner join angie.dbo.markets m2 with (nolock) on m.market_id__C = m2.marketid

where c.Background_Check_Authorization_Date_Sent__c >= DATEADD(year,-1,GETDATE())
and c.BGC_Status__c in ('pass','fail')
and c.BGC_Completion_Date__c is not null
and c.BGC_Completion_Date__c >= c.Background_Check_Authorization_Date_Sent__c

and c.background_check_authorization_date_sent__C not in 
('2023-04-18 10:45:00:00000')

如果我省略了排除该特定时间戳的最终检查,它运行良好。但我实际上需要排除当时的所有条目。因此,问题出在该日期的条目中的某个地方,但由于查询的性质,我无法找到格式错误的字符串,例如,它正在验证需要哪些日期,但在到达损坏/格式错误的条目时失败。如果我在“where”语句中省略日期验证,我会得到 4M 结果。

感谢您的帮助!

sql-server 日期转换

评论

1赞 Jeroen Mostert 5/11/2023
TRY_CONVERT是你在这里的朋友;结果将是转换失败。请注意,优化程序并不局限于 首先过滤 中的子句,因此,排除其中格式错误的记录并不能防止失败,因为这可能发生在查询的前面步骤中。NULLWHERECONVERT
0赞 Nathan Wenger 5/11/2023
这会告诉我 dbo 中的哪一行包含格式错误的字符串吗?
1赞 Jeroen Mostert 5/11/2023
如果你做一个 ,是的。WHERE TRY_CONVERT(...) IS NULL
0赞 Joel Coehoorn 5/11/2023
fwiw,末尾的 datetime 文本不是 SQL Server 的正确格式。由于历史原因,这些文字应该是(日期中没有破折号)或(分隔日期和时间部分)。20230418 10:45:00:000002023-04-18T10:45:00:00000T
1赞 Jeroen Mostert 5/11/2023
顺便说一句,到处放是一个坏习惯。如果查询不会阻止其他查询,请考虑使用快照隔离。NOLOCK

答:

0赞 Joel Coehoorn 5/11/2023 #1

假设 SQL Server 基于错误的文本,我能够复制该问题:

https://dbfiddle.uk/qqw13556

简而言之,日期文字末尾的 0 太多了,您应该这样做:

and c.background_check_authorization_date_sent__C not in 
    ('2023-04-18T10:45:00.000')

还要注意日期和时间部分之间的额外部分,这对于 SQL Server 来说确实是正确的,但原始部分则不然。如果你愿意,你也可以这样做:T

and c.background_check_authorization_date_sent__C not in 
    ('20230418 10:45:00.000')

但再说一遍:原始格式最终会给你带来麻烦,你应该避免它。

评论

0赞 Nathan Wenger 5/11/2023
这奏效了。测试了一下,从 4 月 18 日开始仍然有条目,这很好。我想排除其中的一些,而不是全部。因此,就时间戳而言,在这个特定日期发生了一些事情。老实说,我真的不在乎是哪一个。继续前进...