Oracle VARCHAR2 字段至今与 substr
Oracle VARCHAR2 field to date with substr
我有一个非常混乱的日期字段,它来自多个系统,每个系统都有自己的日期格式。
我有:
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'
另外,如何解释不同系统的不同日期格式?不幸的是,没有我可以使用的系统标识符。
这是一些日期的图片:
07-JAN-19 01.53.47.702000000
2019 年 1 月 7 日 01.53.47.992000000
2019 年 1 月 7 日 01.53.48.186000000
2019 年 1 月 7 日 01.53.48.360000000
2019 年 1 月 7 日 01.53.48.548000000
2019 年 1 月 7 日 01.53.48.709000000
2019 年 1 月 7 日 01.53.48.900000000
2019 年 1 月 20 日 22.49.30.801000000
2019 年 1 月 20 日 22.49.30.014000000
2019 年 1 月 20 日 22.49.33.968000000
您可以编写一些开关逻辑,使用适当的掩码将每个时间戳字符串转换为真正的时间戳。这是一个例子:
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;
但这里最好的长期修复可能是修复您的源数据,使传入的时间戳全部标准化,并采用 Oracle 可以轻松使用的格式。
你可能想多了。默认情况下,Oracle 的日期转换非常灵活,这既是好事也是坏事。在这种情况下,如果您只有显示的格式,则可以使用单一格式掩码完成转换:
to_timestamp(created_on, 'DD-MM-RRRR HH24:MI:SS.FF')
带有一些 made-up 数据的演示:
-- 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
当然,这仍然必须假设使用月份 names/abbreviations 的任何字符串都使用您的会话使用的相同语言。不过你对此无能为力。
然后可以与时间戳文字进行比较:
where to_timestamp(created_on, 'DD-MM-RRRR HH24:MI:SS.FF') >= timestamp '1970-01-01 00:00:00'
and to_timestamp(created_on, 'DD-MM-RRRR HH24:MI:SS.FF') < timestamp '1970-02-01 00:00:00'
我有一个非常混乱的日期字段,它来自多个系统,每个系统都有自己的日期格式。
我有:
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'
另外,如何解释不同系统的不同日期格式?不幸的是,没有我可以使用的系统标识符。
这是一些日期的图片:
07-JAN-19 01.53.47.702000000
2019 年 1 月 7 日 01.53.47.992000000
2019 年 1 月 7 日 01.53.48.186000000
2019 年 1 月 7 日 01.53.48.360000000
2019 年 1 月 7 日 01.53.48.548000000
2019 年 1 月 7 日 01.53.48.709000000
2019 年 1 月 7 日 01.53.48.900000000
2019 年 1 月 20 日 22.49.30.801000000
2019 年 1 月 20 日 22.49.30.014000000
2019 年 1 月 20 日 22.49.33.968000000
您可以编写一些开关逻辑,使用适当的掩码将每个时间戳字符串转换为真正的时间戳。这是一个例子:
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;
但这里最好的长期修复可能是修复您的源数据,使传入的时间戳全部标准化,并采用 Oracle 可以轻松使用的格式。
你可能想多了。默认情况下,Oracle 的日期转换非常灵活,这既是好事也是坏事。在这种情况下,如果您只有显示的格式,则可以使用单一格式掩码完成转换:
to_timestamp(created_on, 'DD-MM-RRRR HH24:MI:SS.FF')
带有一些 made-up 数据的演示:
-- 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
当然,这仍然必须假设使用月份 names/abbreviations 的任何字符串都使用您的会话使用的相同语言。不过你对此无能为力。
然后可以与时间戳文字进行比较:
where to_timestamp(created_on, 'DD-MM-RRRR HH24:MI:SS.FF') >= timestamp '1970-01-01 00:00:00'
and to_timestamp(created_on, 'DD-MM-RRRR HH24:MI:SS.FF') < timestamp '1970-02-01 00:00:00'