将日期为“ 31. 12. 2019”和“ 7/2020”的字符串有效转换为日期类型?

时间:2020-07-23 06:43:15

标签: sql sql-server tsql

我正在导入包含日期的CSV文件,这些文件的格式有两种:

  • 31. 12. 2019
  • 7/2020

这两种形式可以交替出现在同一列中;因此,解决方案的一部分必须是表单的检测。

由于第二个表单7/2020不包含日期信息,因此我将1用作日期。

到目前为止,我只处理了使用可预测日期形式的记录子集。我遵循了CONVERT()函数(https://docs.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql)的T-SQL文档。假设@date = '31. 12. 2019'然后完成以下转换:

    CONVERT(date, @date, 104) AS my_date         -- the German form

对于@date = '7/2020',请执行以下操作:

    CONVERT(date, '1/' + @date, 103) AS my_date  -- the British/French form

现在,如果我(事先)不知道@date包含什么形式,该如何转换?

实际上,日期不在@date变量中。相反,它是SELECT查询中的字段值,例如xdate。我希望代码看起来像这样:

    CASE WHEN /* detect the British/French case */ THEN CONVERT(date, '1/' + xdate, 103)
         WHEN /* detect the German case */ THEN CONVERT(date, xdate, 104)
         ELSE NULL -- this does not happen, anyway...
    END AS my_date

...但是可能会有更好的方法。

3 个答案:

答案 0 :(得分:6)

如果我正确理解了这个问题,则可能的解决方案是将COALESCE()TRY_CONVERT()组合在一起:

声明:

SELECT COALESCE(
   TRY_CONVERT(date, xdate, 104), 
   TRY_CONVERT(date, '1/' + xdate, 103)
) AS xdate
FROM (VALUES
   ('31. 12. 2019'),
   ('7/2000'),
   ('wrong date 12/12')
) v (xdate)

结果:

xdate
----------
2019-12-31
2000-07-01
null

答案 1 :(得分:2)

简单的charindex可以让您指示字符串是否包含斜杠(/)-如果文本格式为m/yyyy或{{ 1}}。

但是,您应该使用dd. mm. yyyy而不是Try_convert,因为不能保证case表达式会短路,这意味着可能会评估所有convert子句。

这是我的写法:

when

答案 2 :(得分:1)

我认为您是使用批量插入或类似的过程将CSV转储到表中,并且该表中存储未处理日期的列是varchar,然后针对表格来处理内容,是吗?

如果是这种情况,并且只有这两种形式,则可以使用likecharindex()。据我所知,性能几乎是相同的,因此无论哪种方法都易于阅读。我个人可能会使用charindex

select case 
          when charindex('/', xdate) > 0 then convert(date, '1/' + xdate, 103)
          else convert(date, xdate, 104)
       end

或使用like

select case 
          when xdate like '%/%' then convert(date, '1/' + xdate, 103)
          else convert(date, xdate, 104)
       end

如果这不是唯一的两种形式,那么您可能想改而try_convert,或者只涵盖您所有的基础