PL / SQL:拆分数字;

时间:2014-03-11 19:58:48

标签: oracle plsql oracle11g oracle-apex

我这里有这个代码:

create or replace FUNCTION calc_length(
    START_TIME IN number, FINISH_TIME IN number)
RETURN NUMBER IS
BEGIN
   DECLARE 
    lhs_start number(2):= LEFT(START_TIME,2);
    lhs_finish number(2):=LEFT(FINISH_TIME,2);
    rhs_start number(2):=RIGHT(START_TIME,2);
    rhs_finish number(2):=RIGHT(FINISH_TIME,2);
    RETURN lhs_finish-lhs_start||'hours'||
           rhs_finish-rhs_start||'minutes'||;
END;​

我正在尝试拆分函数中给出的数字,并将左侧(lhs)2个数字和右侧2个数字分开。函数传递的数字格式始终为4位数字。

e.g。 " 1245"

你能帮我一把吗?

2 个答案:

答案 0 :(得分:1)

快速而肮脏的黑客:

create or replace FUNCTION calc_length(START_TIME number,
                                       FINISH_TIME number)
RETURN VARCHAR2 IS
    result varchar2(30);
    lhs_start number(2) := FLOOR(START_TIME / 100);
    lhs_finish number(2) := FLOOR(FINISH_TIME / 100);
    rhs_start number(2) := (START_TIME / 100 - FLOOR(START_TIME / 100)) * 100;
    rhs_finish number(2) := (FINISH_TIME / 100 - FLOOR(FINISH_TIME / 100)) * 100;

BEGIN    
    if (rhs_finish - rhs_start) > 0 then
      result := to_char(lhs_finish - lhs_start) || ' hours ' ||
                to_char(rhs_finish - rhs_start) || ' minutes';
    else
      result := to_char(lhs_finish - lhs_start - 1) || ' hours ' ||
                to_char(rhs_finish - rhs_start + 60) || ' minutes';
    end if;
    return result;
END calc_length;

注意:我更新了代码以处理负的分钟间隔,但我必须警告整个方法是完全错误的。要计算时间间隔,最好使用适当的数据类型(datetimeinterval)。

答案 1 :(得分:0)

将输入格式转换为Oracle date数据类型,然后才进行数学运算:

create or replace function calc_length(
  start_time in number,
  finish_time in number
) return varchar2 is
  v_start_hours constant pls_integer :=
    floor(start_time / 100);
  v_start_minutes constant pls_integer :=
    start_time - (v_start_hours * 100);

  v_finish_hours constant pls_integer :=
    floor(finish_time / 100);
  v_finish_minutes constant pls_integer :=
    finish_time - (v_finish_hours * 100);

  v_start_time constant date :=
    to_date(v_start_hours, 'HH24') + (v_start_minutes / 1440);
  v_finish_time constant date :=
    to_date(v_finish_hours, 'HH24') + (v_finish_minutes / 1440);

  v_len_hours constant pls_integer :=
    extract(hour from (v_finish_time - v_start_time) day to second);
  v_len_minutes constant pls_integer :=
    extract(minute from (v_finish_time - v_start_time) day to second); 
begin
  return v_len_hours || ':' || v_len_minutes;
end;
/
show errors

col start_ for 99999
col finish for 99999
col length for a10

with data_ as (
  select 0000 as start_, 0127 finish from dual union
  select 0800,           1000        from dual union
  select 1000,           1000        from dual union
  select 1000,           1100        from dual union
  select 1000,           1145        from dual union
  select 2345,           0115        from dual
)
select start_, finish, calc_length(start_, finish) as length from data_;

结果:

START_ FINISH LENGTH
------ ------ ----------
     0    127 1:27
   800   1000 2:0
  1000   1000 0:0
  1000   1100 1:0
  1000   1145 1:45
  2345    115 -22:-30

6 rows selected.

请注意,不考虑条件start_time > finish_time,因此格式不正确。修复这个作为OP的练习!