Oracle Split

关于Oracle中split函数的实现以及函数递归的举例。

今天看到网友提出了这么一个问题。

看下面这张表:
指标编号 计算公式 指标值 可分解标志
A (B+C)+E ? 1
B 10 0
C D+E ? 1
D 30 0
E 5 0

标志为0的指标值是固定的,标志为1的指标值根据公式去计算。

我觉得这个问题很有意思,利用函数递归即可实现,当然需要对公式进行解析,这里我使用了类似于split的自建函数来实现。下面是方法——

创建类型tbl_str,
创建函数to_table,
创建测试表Test,
创建公式符号表expression,
创建函数f_test_get_value,

目前仅支持+ - * / ( ),如果需要别的符号自己加在表expression中.
Test表中的Formula字段每个字符都要用空格分开,例如 ( B + C ) + E
代码如下:

/*************************************************************************************/

create or replace type tbl_str as table of varchar2(4000);
/*********************************************************
/* Description:字定义类型,用于to_table函数
/* Author:He Yixiang
*********************************************************/
/
create or replace function to_table(pv_str varchar2,pv_split varchar2) return tbl_str
as
ltab tbl_str := tbl_str();
pos integer := 0;
ls varchar2(4000) := pv_str;
/*********************************************************
/* Description:同Split函数
/* Author:He Yixiang
*********************************************************/
begin
pos := instr(ls,pv_split);
while pos > 0 loop
ltab.extend;
ltab(ltab.count) := substr(ls,1,pos - 1);
ls := substr(ls,pos + length(pv_split));
pos := instr(ls,pv_split);
end loop;
ltab.extend;
ltab(ltab.count) := ls;
return ltab;
end;
/
create table test (id char(1),formula varchar2(100),value number,flag char(1));
insert into test select 'A','( B + C ) + E',null,1 from dual;
insert into test select 'B',null,10,0 from dual;
insert into test select 'C','D + E',null,1 from dual;
insert into test select 'D',null,30,0 from dual;
insert into test select 'E',null,5,0 from dual;
commit;
create table expression (exp_value char(1));
insert into expression (exp_value) values ('+');
insert into expression (exp_value) values ('-');
insert into expression (exp_value) values ('*');
insert into expression (exp_value) values ('/');
insert into expression (exp_value) values ('(');
insert into expression (exp_value) values (')');
commit;
create or replace function f_test_get_value(pc_id in char) return number is
Result number;
c_flag char(1);
type curtype is ref cursor;
cur curtype;
c_para char(1);
v_sqlstr varchar2(4000);
n_count number;
/*********************************************************
/* Description:根据表test中的公式Formula计算返回Value值
/* Author:He Yixiang
*********************************************************/
begin
select flag into c_flag from test where id=pc_id;
if c_flag='0' then
select value into Result from test where id=pc_id;
else
open cur for
select column_value from table(cast(to_table((select formula from test where id=pc_id),' ') as tbl_str));
v_sqlstr:='select ';
loop
fetch cur into c_para;
exit when cur%notfound;
select count(*) into n_count from expression where exp_value=c_para;
if n_count>0 then
v_sqlstr:=v_sqlstr||c_para;
else
v_sqlstr:=v_sqlstr||f_get_value(c_para);
end if;
end loop;
v_sqlstr:=v_sqlstr||' from dual';
execute immediate v_sqlstr into Result;
close cur;
end if;
return(Result);
end f_test_get_value;
/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值