【问题标题】:Incorrect Date Parsing日期解析不正确
【发布时间】:2020-12-03 18:52:18
【问题描述】:

您能帮我确定我做错了什么还是这是 SQL Server 错误?

我使用的是美国 SQL Server 2016 Enterprise Server。当我设置DATEFORMAT 时,我没有得到预期的结果。请看代码中的cmets。

DECLARE @received varchar(50)

--I expect this to fail, but I get June 11, 2012.
SET DATEFORMAT 'ydm' 
SET @received = '11/JUN/12'

SELECT 
     [month]= DATENAME(month, TRY_CAST(@received as datetime ))
    ,[day]  = DATENAME(day, TRY_CAST(@received as datetime ))
    ,[year] = DATENAME(year, TRY_CAST(@received as datetime ))


--I expect this to be June 12, 2011, but I get June 11, 2012
SET DATEFORMAT 'ymd' 
SET @received = '11/JUN/12'

SELECT 
     [month]= DATENAME(month, TRY_CAST(@received as datetime ))
    ,[day]  = DATENAME(day, TRY_CAST(@received as datetime ))
    ,[year] = DATENAME(year, TRY_CAST(@received as datetime ))

关于我为什么尝试验证上述内容而不是使用 2011/06/12 的背景信息: 我们从世界各地、各种仓库管理系统和具有不同程度技术专长的来源获取平面文件中的数据提取。有时我们的客户可以生成数据,而其他时候,他们通过分包合同从系统中获取数据。我们一次处理数百万行。因此,我们尽最大努力以他们提交的格式验证他们提交的日期。要求重新提交非常不方便,而且会花钱和延误。即使我们要求首选格式,我们也并非总是第一次就得到它。

【问题讨论】:

  • 我不能告诉你为什么,但这是因为'11/JUN/12' 不是有效的日期格式。如果你使用'11/06/12',你会得到预期的结果。
  • 首先不要使用字符串代替日期。使用date 类型的字段和参数。 @received 不是日期,它是一个可以包含任何内容的字符串,包括potato4/7/20207/4/2020。这三种情况的日期分别是什么时候?
  • 它没有帮助,但DATEFORMAT 的参数并不意味着在引号中。
  • 您为什么认为/12 表示2012 年?为什么不是 2012 年?为什么要在导致 Lloyd's 等主要银行下线的那一年重新引入 Y2K,这是 IT 领域最严重和最昂贵的失败?早在一月份,这是个热门新闻。当事情不可避免地出错时,你甚至不能声称自己无知

标签: sql sql-server datetime try-cast


【解决方案1】:

您遇到的问题是 dateformat 仅限于使用其中包含数值的日期。

JUN 更改为 6 将导致第二个示例按预期工作,而第一个示例将在 2011 年 12 月 6 日返回。原因是因为所有支持的 @ format argument 的 987654321@ 对应于 1 位或 2 位数字形式的日期和月份以及 2 位和 4 位数字形式的年份,可选斜杠 (/)、连字符 (-) 或句点 (.) 作为分隔符。所以例如 ymd 对应于 [yy]yy, [m]m, dd 就是这样。

我不知道 casttry_cast 中的什么机制会导致回退行为。

SET DATEFORMAT 'ymd' 
SET @received = '11/6/12'

SELECT 
     [month]= DATENAME(month, CAST(@received as datetime ))
    ,[day]  = DATENAME(day, CAST(@received as datetime ))
    ,[year] = DATENAME(year, CAST(@received as datetime ))

如果您需要将月份作为中间的缩写,那么使用 parse 和 ja-JP 文化似乎是可能的。以下示例将返回您在第二个示例中所需的结果。

SET @received = '11/JUN/12'
SELECT 
     [month]= DATENAME(month, TRY_PARSE(@received AS date USING 'ja-JP'))
    ,[day]  = DATENAME(day, TRY_PARSE(@received AS date USING 'ja-JP'))
    ,[year] = DATENAME(year, TRY_PARSE(@received AS date USING 'ja-JP'))

【讨论】:

  • 我不得不提一下,在劳合社因 2 位数年份而倒闭的那一年使用 2 位数年份是荒谬的,人们收到了 90 年逾期贷款分期付款的通知。
  • 谢谢丹尼尔。我可以使用带有“ja-JP”文化的 Try_Parse 来解析这种情况。它有助于。我在问题中添加了一条评论,解释了我为什么要尝试验证这种不寻常的格式。
  • @AleBel,如果这可行,你可以给答案一个检查,这样没有人会试图回答。
猜你喜欢
  • 2013-07-10
  • 1970-01-01
  • 1970-01-01
  • 2022-10-02
  • 2016-01-10
  • 1970-01-01
  • 2021-06-11
  • 1970-01-01
  • 2018-04-06
相关资源
最近更新 更多