How do you select a varchar2 field in the format of 'HH24:MI:SSxFF6' as an INTERVAL HOUR TO SECOND(6)?

梦想与她 提交于 2019-12-11 07:39:18

问题


The following query succeeds:

SELECT INTERVAL '00:00:00.000000' HOUR TO SECOND(6)
FROM DUAL;

The following fails:

SELECT INTERVAL time_field HOUR TO SECOND(6) -- time_field is a VARCHAR2(15)
FROM some_table;

w/ the following error:

ORA-00923: FROM keyword not found where expected

How do I fix my second query to pull back an HOUR TO SECOND INTERVAL?

When I try:

SELECT cast(time_field AS INTERVAL HOUR TO SECOND(6))
FROM some_table

I get the following:

ORA-00963: unsupported interval type

TEST SETUP:

CREATE TABLE some_table (
   time_field VARCHAR2(50)
);

INSERT ALL
INTO some_table (time_field) VALUES ('10:00:00.000000')
INTO some_table (time_field) VALUES ('12:00:00.000000')
INTO some_table (time_field) VALUES ('15:00:00.000000')
INTO some_table (time_field) VALUES ('17:00:00.000000')
INTO some_table (time_field) VALUES ('20:00:00.000000')
INTO some_table (time_field) VALUES (NULL)
SELECT * FROM DUAL;

回答1:


You can use the TO_DSINTERVAL function; example here using a CTE to replicate your table:

WITH some_table AS (SELECT '00:00:00.000000' AS time_field FROM dual)
SELECT TO_DSINTERVAL('0 ' || time_field)
FROM some_table;

TO_DSINTERVAL('0'||TIME_FIELD)
---------------------------------------------------------------------------
+000000000 00:00:00.000000000

Note that to make the format something the function recognises, you have to supply a 'days' part, hence the prepending of the dummy '0 ' string.

Your fixed-value query returns a slightly different format (or at least displays slightly differently; interval daa types do not have format models in quite the same way as dates, so not sure how to express that accurately):

SELECT INTERVAL '00:00:00.000000' HOUR TO SECOND(6)
FROM DUAL;

INTERVAL'00:00:00.000000'HOURTOSECOND(6)
---------------------------------------------------------------------------
+00 00:00:00.000000

To replicate that you can cast this if you need to:

WITH some_table AS (SELECT '00:00:00.000000' AS time_field FROM dual)
SELECT CAST(TO_DSINTERVAL('0 ' || time_field) AS INTERVAL DAY TO SECOND(6))
FROM some_table;

CAST(TO_DSINTERVAL('0'||TIME_FIELD)ASINTERVALDAYTOSECOND(6))
---------------------------------------------------------------------------
+00 00:00:00.000000

... or just:

WITH some_table AS (SELECT '00:00:00.000000' AS time_field FROM dual)
SELECT CAST('0 ' || time_field AS INTERVAL DAY TO SECOND(6))
FROM some_table;

CAST('0'||TIME_FIELDASINTERVALDAYTOSECOND(6))
---------------------------------------------------------------------------
+00 00:00:00.000000

... which is pretty much what @catcall first suggested, but this also needs the '0 ' prepended, or you get an ORA-01867. (Or, if you try to use HOUR TO SECOND, ORA-00963, even with the prepended day value). However, I guess (and it is just a guess, though very slightly educated) that it's doing an implicit TO_DSINTERVAL or similar, and I think I'd prefer to use an explicit one so I was sure what's happening. That might just be me, though...


Using your sample data I too get an ORA-01867, but it's caused by the null value. You can use a case to leave that as null in the result:

SELECT CASE WHEN time_field IS NULL THEN null
    ELSE CAST('0 ' || time_field AS INTERVAL DAY TO SECOND(6)) END
FROM some_table;

CASEWHENTIME_FIELDISNULLTHENNULLELSECAST('0'||TIME_FIELDASINTERVALDAYTOSECO
---------------------------------------------------------------------------
+00 10:00:00.000000
+00 12:00:00.000000
+00 15:00:00.000000
+00 17:00:00.000000
+00 20:00:00.000000


6 rows selected.



回答2:


I'd think this (untested) cast were called for.

SELECT cast (time_field as interval hour to second(6))
FROM some_table;

Your column will have to be of a type that's compatible with a cast to interval, and it will have to contain data that can be interpreted as an interval.

Oracle 11g docs for CAST


Sample code

create table test (
  interval_type interval day to second,
  varchar_type varchar2(35) 
);

insert into test values (
  (current_timestamp - to_date(current_date)),
  (current_timestamp - to_date(current_date))
);

select 
  interval_type, 
  varchar_type
from test;

INTERVAL_TYPE                                                                              VARCHAR_TYPE
{"Bytes":[-128,0,0,0,78,95,84,-102,-92,-83,-64],"ShareBytes":null,"Length":11,"Stream":{}} +000000000 18:35:24.000000

select 
  interval_type, 
  cast (varchar_type as interval day to second)
from test;

INTERVAL_TYPE                                                                               CAST(VARCHAR_TYPEASINTERVALDAYTOSECOND)
{"Bytes":[-128,0,0,0,78,95,84,-102,-92,-83,-64],"ShareBytes":null,"Length":11,"Stream":{}}  {"Bytes":[-128,0,0,0,78,95,84,-128,0,0,0],"ShareBytes":null,"Length":11,"Stream":{}}


来源:https://stackoverflow.com/questions/12376901/how-do-you-select-a-varchar2-field-in-the-format-of-hh24missxff6-as-an-inter

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!