有这样一条sql:
select c_lx from t_table where n_id=1;
查询结果为:
1;2;3;4;5;6;
有没有这样一个函数,将该记录以‘;’切分并转换为多行的结果集,如:
1 2 3 4 5 6
注意:是结果集(6行),而不是一条纵向显示的记录。
我知道oracle有wm_concat函数,可以将多条记录合并成一条,并以逗号分割。
使用场景:
如代码类型,控件保存时是以‘5;6;7;8;9;10;’的格式保存在一个字段里的,一般对应的代码名称都会冗余一列,如‘工人;农民;干部;’,但是很多地方并没有冗余,在展示的时候,翻译代码时便出现了麻烦,所以如果存在一个函数,将该代码值切分并以多条结果集返回,那么一个表连接即可将代码翻译,如:
select c_mc from t_dm where n_dm in(select xxx from xxx) and n_id=xxx;
不知道有没有这样的一个函数?在搜索之后我没有找到,无奈自己实现了一个:
创建类型:
create or replace type type_dm as object ( DM number(5) ); create or replace type list_dm as table of type_dm;
函数定义:
create or replace function FN_ROW2Column(c_tag varchar) return list_dm pipelined as v_type_dm type_dm; c_tmp number(3); c_middle varchar(50); begin c_middle := c_tag; loop c_tmp := substr(c_middle, 1, instr(c_middle, ';') - 1); c_middle := substr(c_middle, instr(c_middle, ';') + 1, length(c_middle)); v_type_dm := type_dm(c_tmp); pipe row(v_type_dm); exit when c_middle is null; end loop; return; end FN_ROW2Column;
测试:
select * from table(FN_ROW2Column('1;23;2;12;5;4;5;5;6;5;5;4;')) 1 23 2 12 5 4 5 5 6 5 5 4
那么在翻译代码时:
select wm_concat(c_mc) from t_dm where n_dm in(select * from table(FN_ROW2Column('1;23;2;12;5;4;5;5;6;5;5;4;'))) and n_id=xxx;
这样一个sql即可完美的将复杂代码翻译完,就是不知道有没有一个内置函数有这样的功能。
加强版的:
--c_tag:要解析的目标字符串,如1;2;3;4 --tag:分隔标记,代表字符串之间的分隔符,如;,默认为';' create or replace function FN_ROW2Column(c_tag varchar, tag varchar default ';') return list_dm pipelined as v_type_dm type_dm; c_tmp number(3); c_middle varchar(50); begin c_middle := c_tag; loop if substr(c_middle, length(c_middle)) != tag then c_middle := c_middle || tag; end if; c_tmp := substr(c_middle, 1, instr(c_middle, tag) - 1); c_middle := substr(c_middle, instr(c_middle, tag) + 1, length(c_middle)); v_type_dm := type_dm(c_tmp); pipe row(v_type_dm); exit when c_middle is null; end loop; exception when others then --出现异常,静默不予处理 -- do nothing; return; end FN_ROW2Column;