在Oracle 12c中将VARCHAR2转换为TIMESTAMP

问题描述

我在表A中有一列为

select create_time from table_a;

值是

08-MAR-19 08.23.47.897000000 PM GMT.

出于某些业务目的,此列已标记为VARCHAR2。现在,我试图获取此列并将其转换为TIMESTAMP,以实现某种目的,如下所示:

SELECT TO_TIMESTAMP(create_time,'DD-MON-YYYY HH.MI.SS.FF AM') from table_a;

但是我遇到了错误

ORA-01830: date format picture ends before converting entire input string

有人可以帮助我将此varchar数据转换为时间戳。我尝试这样做的原因是,我需要将此时间从一个时区转换为另一个时区: 例如:

SELECT FROM_TZ(TO_TIMESTAMP(create_time,'DD-MON-YYYY HH.MI.SS.FF AM'),'UTC') AT TIME ZONE 'CET' from table_a;

解决方法

SQL> select replace('08-MAR-19 08.23.47.897000000 PM GMT','GMT','') AS RESULT from dual 
  ;

RESULT
--------------------------------
08-MAR-19 08.23.47.897000000 PM

SQL> select to_timestamp(replace('08-MAR-19 08.23.47.897000000 PM GMT','')) as RESULT from dual ;

RESULT
---------------------------------------------------------------------------
08-MAR-19 08.23.47.897000000 PM

SQL> select from_tz(to_timestamp(replace('08-MAR-19 08.23.47.897000000 PM GMT','')),'UTC') AT TIME ZONE 'CET' AS RESULT from dual ;

RESULT
---------------------------------------------------------------------------
08-MAR-19 09.23.47.897000000 PM CET

SQL>
,

结尾的四个字符 GMT不在您的格式字符串中占

SELECT TO_TIMESTAMP('08-MAR-19 08.23.47.897000000 PM GMT','DD-MON-YYYY HH.MI.SS.FF AM') from dual;

以下内容可以解决此问题:

SELECT TO_TIMESTAMP(substr(create_time,1,LENGTH(create_time) -4),'DD-MON-YYYY HH.MI.SS.FF AM') t from dual;

,

尝试一下。

select  TO_TIMESTAMP( REPLACE(ts,'')) from test_timestamp;
,

使用GMT删除REPLACE

WITH A AS (SELECT REPLACE('08-MAR-19 08.23.47.897000000 PM GMT','') AS D FROM DUAL)
SELECT TO_TIMESTAMP (D,'DD-MON-YYYY HH.MI.SS.FF AM')
  FROM A
 
,

做类似的事情:

to_timestamp(replace(create_time,null))

取决于您的NLS设置,包括时间戳格式(尤其是具有RR年掩码)和月份缩写的语言。这样做会更安全:

to_timestamp(replace(create_time,' GMT',null),'DD-MON-RR HH.MI.SS.FF AM','NLS_DATE_LANGUAGE=ENGLISH')

如果时区并非始终是格林尼治标准时间,而是始终是有效且可识别的区域(例如,不是BST),那么您可能希望保留包括该时区的完整日期/时间:

to_timestamp_tz(create_time,'DD-MON-RR HH.MI.SS.FF AM TZR','NLS_DATE_LANGUAGE=ENGLISH')

如果您希望将其作为普通时间戳记,则可以对其进行投射,可以先更改为特定区域:

cast(to_timestamp_tz(create_time,'NLS_DATE_LANGUAGE=ENGLISH') as timestamp)

cast(to_timestamp_tz(create_time,'NLS_DATE_LANGUAGE=ENGLISH') at time zone 'Asia/Tokyo' as timestamp)

或标准化为UTC(当然,它们不会影响GMT值,因为它们本质上是相同的):

sys_extract_utc(to_timestamp_tz(create_time,'NLS_DATE_LANGUAGE=ENGLISH'))

db<>fiddle