Home > Back-end >  How to convert VARCHAR2 to INTERVAL
How to convert VARCHAR2 to INTERVAL

Time:11-09

I want to convert a VARCHAR2-value like '-28:15:00' to INTERVAL.

With a literal value, this works:

select interval '-09:11:36' hour to second from dual;

However, this does not (ORA-00923: FROM keyword not found where expected):

select interval MY_VARCHAR hour to second from MY_TABLE;
--comparable to select interval to_char(sysdate, 'hh:mm:ss') hour to second from dual;

My assumption is that the literal value is implicitly cast while the explicit varchar-value from MY_VARCHAR (or char from to_char respectively) is not valid between "interval" and "hour".

CAST like this does not work (ORA-00963: unsupported interval type):

select cast(MY_VARCHAR as interval hour to second) from MY_TABLE;
--comparable to select cast('09:11:36' as interval hour to second) from dual;

What does work is concatenating '0 ' as the day-value and cast it to INTERVAL DAY TO SECOND:

select cast('0 ' || '09:11:36' as interval day to second) from dual;

However this only works for positive values, and as long as the value for hour is below 24. Is there a better solution than dissecting the VARCHAR-value with CASE, SUBSTR and so on?

CodePudding user response:

You need the minus sign before the days to cast it to an interval:

SELECT value,
       CAST( REGEXP_REPLACE(value, '^(-)?', '\10 ') AS INTERVAL DAY TO SECOND )
         AS interval_value
FROM   table_name

or, using simple string functions, which slightly more to type but probably more efficient (as regular expressions are slow):

SELECT value,
       CAST(
         CASE
         WHEN value LIKE '-%'
         THEN '-0 ' || SUBSTR(value, 2)
         ELSE '0 ' || value
         END
         AS INTERVAL DAY TO SECOND
       ) AS interval_value
FROM   table_name

Which, for the sample data:

CREATE TABLE table_name (value) AS
  SELECT '-09:11:36' FROM DUAL UNION ALL
  SELECT '09:11:36' FROM DUAL;

Both output:

VALUE INTERVAL_VALUE
-09:11:36 -00 09:11:36.000000
09:11:36 00 09:11:36.000000

enter image description here

... so your first query gets ORA-00923.

And the cast() function only supports certain conversions:

Note 1: Datetime/interval includes DATE, TIMESTAMP, TIMESTAMP WITH TIMEZONE, TIMESTAMP WITH LOCAL TIME ZONE, INTERVAL DAY TO SECOND, and INTERVAL YEAR TO MONTH.

so you can't cast(... as interval hour to second), and that will throw ORA-00963.

  • Related