PL/SQL:拆分数字;

Posted

技术标签:

【中文标题】PL/SQL:拆分数字;【英文标题】:PL/SQL: splitting numbers; 【发布时间】:2014-03-11 19:58:47 【问题描述】:

我这里有这段代码:

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 位数字。

例如“1245”

你能帮我一下吗?

【问题讨论】:

为什么不使用 varchar2 或 to_char? @user2672165 因为它必须是数字格式。它是一个要求。不要问:) 【参考方案1】:

快速而肮脏的 hack:

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)。

【讨论】:

这会产生预期的结果吗? select calc_length(1245,1300) from dual;1 hours -45 minutes【参考方案2】:

将输入格式转换为 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 练习!

【讨论】:

以上是关于PL/SQL:拆分数字;的主要内容,如果未能解决你的问题,请参考以下文章

Python 正则表达式拆分 PL/SQL 指令

Pl/SQL 拆分表

将行拆分为多行 PL/SQL

使用 pl/sql 或 sql 将数据拆分到学生表中的多个列

PL SQL从用逗号分隔的字符串创建数字数组[重复]

如何在 pl/sql 中将街道值拆分为原子?