在Oracle SQL中将秒值转换为ISO 8601格式的持续时间

时间:2016-04-04 10:00:47

标签: sql oracle iso

我希望将持有秒数(音乐持续时间)的Oracle数据库列转换为ISO 8601格式的持续时间。但我到处寻找一个Oracle程序或一块SQL,但没有成功。我看到有其他语言的例子,但没有Oracle SQL或PL / SQL。

以下是the ISO standard的一些信息。

我在Oracle 11g数据库上。

2 个答案:

答案 0 :(得分:1)

您还可以使用EXTRACT功能:

WITH t AS (
  SELECT INTERVAL '59' SECOND AS duration FROM dual
  UNION ALL SELECT INTERVAL '60' SECOND FROM dual
  UNION ALL SELECT INTERVAL '61' SECOND FROM dual
  UNION ALL SELECT INTERVAL '3599' SECOND FROM dual
  UNION ALL SELECT INTERVAL '3600' SECOND FROM dual
  UNION ALL SELECT INTERVAL '86399' SECOND FROM dual
)
SELECT duration,
    'PT'
        ||NULLIF(EXTRACT(HOUR FROM duration)||'H', '0H') 
        ||NULLIF(EXTRACT(MINUTE FROM duration)||'M', '0M') 
        ||NULLIF(EXTRACT(SECOND FROM duration)||'S', '0S')  
    AS iso_value
FROM t;

答案 1 :(得分:0)

Oracle有一种间隔数据类型,您可以将其转换为持续时间,但您无法对其进行格式化。最简单的方法是使用mod和trunc将其分解为完整的小时和分钟以及剩余的秒数。

使用一些示例数据:

with t (duration) as (
  select 59 from dual
  union all select 60 from dual
  union all select 61 from dual
  union all select 3599 from dual
  union all select 3600 from dual
  union all select 86399 from dual
)
select duration,
  numtodsinterval(duration, 'SECOND') as interval_value,
  'PT'
    || case when trunc(duration/3600) > 0 then trunc(duration/3600) || 'H' end
    || case when trunc(duration/3600) > 0 or trunc(mod(duration, 3600)/60) > 0
        then trunc(mod(duration, 3600)/60) || 'M' end
    || trunc(mod(duration, 60)) || 'S' as iso_value
from t;

  DURATION INTERVAL_VAL ISO_VALUE  
---------- ------------ ------------
        59 0 0:0:59.0   PT59S       
        60 0 0:1:0.0    PT1M0S      
        61 0 0:1:1.0    PT1M1S      
      3599 0 0:59:59.0  PT59M59S    
      3600 0 1:0:0.0    PT1H0M0S    
     86399 0 23:59:59.0 PT23H59M59S 

我假设持续时间永远不会超过24小时,而你只需要整秒;但如果有必要,可以处理更长的持续时间和更高的精确度。

我还猜测你要排除最高的可选部分,所以你不会显示0H说;但是,即使它们为零,你已经显示出想要显示分钟和秒数的小时数。如果没有,你可以调整(或删除)case语句。

要始终显示所有三个部分:

select duration,
  numtodsinterval(duration, 'SECOND') as interval_value,
  'PT' || trunc(duration/3600) || 'H'
    || trunc(mod(duration, 3600)/60) || 'M'
    || trunc(mod(duration, 60)) || 'S' as iso_value
from t;

  DURATION INTERVAL_VAL ISO_VALUE  
---------- ------------ ------------
        59 0 0:0:59.0   PT0H0M59S   
        60 0 0:1:0.0    PT0H1M0S    
        61 0 0:1:1.0    PT0H1M1S    
      3599 0 0:59:59.0  PT0H59M59S  
      3600 0 1:0:0.0    PT1H0M0S    
     86399 0 23:59:59.0 PT23H59M59S 

永不显示零件:

select duration,
  numtodsinterval(duration, 'SECOND') as interval_value,
  'PT'
    || case when trunc(duration/3600) > 0 then trunc(duration/3600) || 'H' end
    || case when trunc(mod(duration, 3600)/60) > 0 then trunc(mod(duration, 3600)/60) || 'M' end
    || case when trunc(mod(duration, 60)) > 0 then trunc(mod(duration, 60)) || 'S' end
    as iso_value
from t;

  DURATION INTERVAL_VAL ISO_VALUE  
---------- ------------ ------------
        59 0 0:0:59.0   PT59S       
        60 0 0:1:0.0    PT1M        
        61 0 0:1:1.0    PT1M1S      
      3599 0 0:59:59.0  PT59M59S    
      3600 0 1:0:0.0    PT1H        
     86399 0 23:59:59.0 PT23H59M59S