迄今为止,Oracle VARCHAR2字段带有substr

时间:2019-05-10 10:10:47

标签: sql oracle to-date varchar2

我有一个非常混乱的日期字段,它由多个系统提供,每个系统都有自己的日期格式。

我有:

  

DD-MM-YY hh:mm:ss.ssss

     

DD-MON-YY hh:mm:ss

     

DD-MM-YYYY hh:mm:ss.ssss

所有这些都存储在 varchar2 字段中。现在,我必须在日期范围之间进行搜索,这导致了我的问题。我该如何处理?

以下是我尝试过的一些代码段:

一个标准的substr效果很好,但是我不能解释不同的日期格式:

select substr(created_on, 1,9) as date2 from rtl.HK_Alerts

理想情况下,如果我能使它工作:

select to_date(created_on, 'dd-mon-yy') as date_convert from rtl.HK_Alerts

然后我可以这样做:

select * from my_table 
    where to_date(created_on, 'dd-mon-yy') > '01-Jan-1970'
    and to_date(***strong text***created_on, 'dd-mon-yy') < '31-Jan-1970'

此外,我该如何考虑来自不同系统的不同日期格式?不幸的是,没有可以使用的系统标识符。

下面是一些日期的图片: created_on_date

19年1月7日01.53.47.702000000
19年1月7日01.53.47.992000000
19年1月7日01.53.48.186000000
19年1月7日01.53.48.360000000
19年1月7日01.53.48.548000000
19年1月7日01.53.48.709000000
19年1月7日01.53.48.900000000
19年1月20日22.49.30.801000000
19年1月20日22.49.30.014000000
19年1月20日22.49.33.968000000

2 个答案:

答案 0 :(得分:3)

您可以编写一些开关逻辑,使用适当的掩码将每个时间戳字符串转换为真正的时间戳。这是一个示例:

SELECT
    created_on,
    CASE WHEN REGEXP_LIKE (created_on, '^[0-9]{2}-[0-9]{2}-[0-9]{4}')
         THEN TO_TIMESTAMP(created_on, 'DD-MM-YYYY HH24:MI:SS.FF') END AS 
         WHEN REGEXP_LIKE (created_on, '^[0-9]{2}-[0-9]{2}-[0-9]{2}')
         THEN TO_TIMESTAMP(created_on, 'DD-MM-RR HH24:MI:SS.FF')
         WHEN REGEXP_LIKE (created_on, '^[0-9]{2}-[A-Z]{3}-[0-9]{2}')
         THEN TO_TIMESTAMP(created_on, 'DD-MON-RR HH24:MI:SS')

created_on_ts     来自rtl.HK_Alerts;

enter image description here

Demo

但是,最好的长期解决方法可能是修复源数据,以使传入的时间戳全部标准化,并且采用Oracle可以轻松使用的格式。

答案 1 :(得分:3)

您可能想得太多。默认情况下,Oracle的日期转换非常灵活,这既好又坏。在这种情况下,如果只有显示的格式,则可以使用单个格式掩码进行转换:

Date

包含一些虚构数据的演示

to_timestamp(created_on, 'DD-MM-RRRR HH24:MI:SS.FF')

当然,这仍然必须假定使用月份名称/缩写的任何字符串都与您的会话使用的语言相同。不过,您对此无能为力。

然后可以根据时间戳字面量进行比较:

-- CTE for sample data
with hk_alerts (created_on) as (
            select '10-05-19 12:34:56' from dual
  union all select '10-05-19 12:34:56.789' from dual
  union all select '10-May-19 12:34:56' from dual
  union all select '10-May-19 12:34:56.789' from dual
  union all select '10-May-2019 12:34:56' from dual
  union all select '10-May-2019 12:34:56.789' from dual
)
-- actual query
select created_on, to_timestamp(created_on, 'DD-MM-RRRR HH24:MI:SS.FF') as date_convert
from hk_alerts;

CREATED_ON               DATE_CONVERT                 
------------------------ -----------------------------
10-05-19 12:34:56        2019-05-10 12:34:56.000000000
10-05-19 12:34:56.789    2019-05-10 12:34:56.789000000
10-May-19 12:34:56       2019-05-10 12:34:56.000000000
10-May-19 12:34:56.789   2019-05-10 12:34:56.789000000
10-May-2019 12:34:56     2019-05-10 12:34:56.000000000
10-May-2019 12:34:56.789 2019-05-10 12:34:56.789000000