【背景】
在进行数据抽取时,源端“时间意义”字段数据为“时间戳格式”,而且字段类型为字符串类型。但是目标端要求,进入数据为date类型,需要清洗。
?
【解决】
遇到这种问题,起初可能会比较棘手,但通过对“时间戳格式”进行简单分析后,我们会发现有法可施。
例如下面这种格式:
'14-JUN-15 08.23.35.048000 PM +08:00','DD MON YYYY HH.MI AM'
可以使用这样的处理方式:
select to_date(replace(substr('14-JUN-15 08.23.35.048000 PM +08:00',1,18),'.',':')||substr('14-JUN-15 08.23.35.048000 PM +08:00',26,3),'DD-MON-YY HH:MI:SS AM') from dual;
处理后的结果如下:
2015/6/14 20:23:35
?
上面的处理方法,其实很简单,就是把时间戳拆分成两部分,然后分别处理后做了一个拼接而已,如下这样分步查询出来就一目了然了,如下:


再来看看正确使用时间戳的方式,如下举例:
create table 实验表
(ID varchar2(32) default sys_guid(),
DATE_TIMESTAMP date default systimestamp,
memo varchar2(32)
);
insert into 实验表 (memo) values(1);
insert into 实验表 (memo) values(2);
insert into 实验表 (memo) values(3);
commit;
select * from 实验表;

也可以使用下面这样的方式,如下:
create table 实验表2
(ID varchar2(32) default sys_guid(),
DATE_TIMESTAMP date default current_timestamp,
memo varchar2(32)
);
insert into 实验表2 (memo) values(1);
commit;
select * from 实验表2;

通过上面演示,我们可以使用current_timestamp或systimestamp获得时间戳,可以看到在以date为类型的字段插入时间戳时,显示的为正常的时间格式,因为已经被oracle进行了隐式转换了,但是如果单独查询会是如何呢?按下面的方式查询:
select sessiontimezone,current_timestamp from dual;

可以看到,时间戳默认是以“14-JUN-15 08.23.35.048000 PM +08:00”格式显示的,这也就意味着如果建表时,“该字段你没有date类型”或“用了varchar2类型但是没有强制转换”的话,存入到该字段的内容是这样格式的。当把该字段抽取到以date为类型的表时,便会遇到问题。
【实验】
构建源端数据表(实验表3)、目标表,如下:
create table 实验表3
(ID varchar2(32) default sys_guid(),
DATE_TIMESTAMP varchar2(50) default current_timestamp,
memo varchar2(50)
);
select * from 实验表3;
insert into 实验表3 (memo) values(1);
insert into 实验表3 (memo) values(2);
insert into 实验表3 (memo) values(3);
insert into 实验表3 (memo) values(4);
commit;
create table 目标表
(ID varchar2(32),
DATE_TIME date,
memo varchar2(50)
);
未处理的抽取操作:

添加“清洗”操作后,抽取数据操作:
INSERT /*+append*/ INTO 目标表 nologging
SELECT
ID ID,
to_date(replace(substr(DATE_TIMESTAMP,1,18),'.',':')||substr(DATE_TIMESTAMP,26,3),'DD-MON-YY HH:MI:SS AM') DATE_TIME,
MEMO MEMO
FROM 实验表3;
commit;
select * from 目标表;

数据在抽取时已经完成了清洗,并且抽取过来了。
?
小知识,简而记之。