设为首页 收藏本站
查看: 626|回复: 0

[经验分享] 运用oracle分解一个用户多个套餐

[复制链接]

尚未签到

发表于 2016-8-10 06:49:58 | 显示全部楼层 |阅读模式
  create or replace function f_table_change(v_table_name varchar2,v_key_col varchar2,v_chang_collist varchar2,v_chang_colcnt integer) return varchar2 is
/*
函数功能:根据输入表名及相关字段信息进行库表数据横向处理
输入参数: v_table_name(源数据表,格式username.table_name)
v_key_col(分组字段,实际要进行分组的字段名)
v_chang_collist(需要横向的字段串多个字段以","分割,最后一个字段无分隔符。例“字段1,字段2,字段3)可以为空
v_chang_colcnt(需要横向的字段数),可以为0
输出参数: Result结果表
执行方式:命令行执行
set serveroutput on;
exec dbms_output.put_line(gmcc.f_table_change('用户名.表名','需要分组的字段','需要横向的字段序列,格式:字段1,字段2,字段3',字段数(与横向字段数一致)));
*/
  vv_username varchar2(32);
vv_tabname varchar2(32);
vv_keycol varchar2(32);
vv_changcollist varchar2(1024);
vv_changcol varchar2(32);
vv_changcolcnt integer;
vv_maxcolcnt integer; --允许横向的最大字段数
  vv_flag integer;
vv_colcnt integer;
  vv_tabtmp varchar2(32); --临时表
vv_tabrsl varchar2(32); --结果表
  vv_ifexists_tab integer; --标识是否存在库表
vv_sql varchar2(4000);
vv_sql1 varchar2(4000);
vv_sql2 varchar2(4000);
vv_sql3 varchar2(4000);
vv_sql1_mid varchar2(4000);
  tb varchar2(32);
vv_rncnt integer; --分组字段记录数标识
max_rncnt integer; --标识分组字段最多的记录数
  Result varchar2(1024);
  begin
  /*初始化参数*/
vv_tabtmp := 'TMP_TABLE';
vv_tabrsl := 'RESULT_TABLE';
  vv_username := substr(upper(trim(v_table_name)),1,instr(trim(v_table_name),'.',1,1)-1);
vv_tabname := substr(upper(trim(v_table_name)),instr(trim(v_table_name),'.',1,1)+1);
vv_keycol := upper(trim(v_key_col));
vv_changcollist := upper(trim(v_chang_collist));
vv_changcolcnt := v_chang_colcnt;
vv_flag := 0;
vv_maxcolcnt := 10;
  /*输入参数核查*/
begin
/*检查是否存在输入用户名*/
execute immediate 'select count(*) from all_users where username = '''||vv_username||'''' into vv_flag;
if( vv_flag = 0 ) then
Result := '输入用户'||vv_username||'不存在,请重新输入。输入格式:username.table_name';
return(Result);
end if;
  /*检查是否存在输入表*/
execute immediate 'select count(*) from all_tables where owner = '''||vv_username||''' and table_name = '''||vv_tabname||'''' into vv_flag;
if( vv_flag = 0 ) then
Result := '输入表'||vv_tabname||'不存在,请重新输入。输入格式:username.table_name';
return(Result);
end if;
  /*检查是否存在输入分组字段名*/
execute immediate 'select count(*) from all_tab_columns where owner = '''||vv_username||''' and table_name = '''||vv_tabname||''' and column_name = '''||vv_keycol||'''' into vv_flag;
if( vv_flag = 0 ) then
Result := '输入分组字段'||vv_keycol||'不存在,请重新输入。';
return(Result);
end if;
  /*检查是否存在输入横向字段名*/
if( vv_changcollist is not null and vv_changcolcnt > 0 and vv_changcolcnt <= vv_maxcolcnt ) then
vv_colcnt := 1;
while( vv_colcnt <= vv_changcolcnt ) loop
/*拆分横向字段串*/
if( vv_colcnt < vv_changcolcnt ) then
if( vv_colcnt = 1 ) then
vv_changcol := substr(upper(trim(vv_changcollist)),1,instr(trim(vv_changcollist),',',1,vv_colcnt)-1);
else
vv_changcol := substr(upper(trim(vv_changcollist)),instr(trim(vv_changcollist),',',1,vv_colcnt-1)+1,instr(trim(vv_changcollist),',',1,vv_colcnt)-instr(trim(vv_changcollist),',',1,vv_colcnt-1)-1);
end if;
else
/*最后一个字段时处理*/
if( vv_changcolcnt = 1 ) then
vv_changcol := substr(upper(trim(vv_changcollist)),1);
else
vv_changcol := substr(upper(trim(vv_changcollist)),instr(trim(vv_changcollist),',',1,vv_changcolcnt-1)+1);
end if;
end if;
  execute immediate 'select count(*) from all_tab_columns where owner = '''||vv_username||''' and table_name = '''||vv_tabname||''' and column_name = '''||vv_changcol||'''' into vv_flag;
if( vv_flag = 0 ) then
Result := '输入横向字段'||vv_changcol||'不存在,请重新输入。输入格式:字段1,字段2,字段3';
return(Result);
end if;
  vv_colcnt := vv_colcnt+1;
end loop;
else
if ( vv_changcolcnt > vv_maxcolcnt ) then
Result := '只允许输入不超过'||vv_maxcolcnt||'个横向字段,请重新输入。输入格式:字段1,字段2,字段3';
return(Result);
end if;
end if;
end;
  /*数据表横向sql语句生成*/
begin
if( vv_changcollist is not null and vv_changcolcnt > 0 ) then
/*有横向字段*/
execute immediate 'select count(1) from all_tables where table_name = '''||vv_tabtmp||''' and owner = '''||vv_username||'''' into vv_ifexists_tab;
if ( vv_ifexists_tab > 0 ) then
execute immediate 'truncate table '||vv_username||'.'||vv_tabtmp;
execute immediate 'drop table '||vv_username||'.'||vv_tabtmp||' purge';
end if;
execute immediate 'create table '||vv_username||'.'||vv_tabtmp||' nologging as
select '||vv_keycol||','||vv_changcollist||',
row_number() over (partition by '||vv_keycol||' order by '||vv_keycol||') rn
from '||vv_username||'.'||vv_tabname
;

vv_rncnt := 1;
execute immediate 'select max(rn) from '||vv_username||'.'||vv_tabtmp into max_rncnt;
while ( vv_rncnt <= max_rncnt ) loop
tb := 'tb'||vv_rncnt;
if ( vv_sql1 is null and vv_sql2 is null ) then
vv_colcnt := 1;
vv_sql1_mid := null;
while( vv_colcnt <= vv_changcolcnt ) loop
/*拆分横向字段串*/
if( vv_colcnt < vv_changcolcnt ) then
if( vv_colcnt = 1 ) then
vv_changcol := substr(upper(trim(vv_changcollist)),1,instr(trim(vv_changcollist),',',1,vv_colcnt)-1);
else
vv_changcol := substr(upper(trim(vv_changcollist)),instr(trim(vv_changcollist),',',1,vv_colcnt-1)+1,instr(trim(vv_changcollist),',',1,vv_colcnt)-instr(trim(vv_changcollist),',',1,vv_colcnt-1)-1);
end if;
else
/*最后一个字段时处理*/
if( vv_changcolcnt = 1 ) then
vv_changcol := substr(upper(trim(vv_changcollist)),1);
else
vv_changcol := substr(upper(trim(vv_changcollist)),instr(trim(vv_changcollist),',',1,vv_changcolcnt-1)+1);
end if;
end if;

if( vv_sql1_mid is null ) then
vv_sql1_mid := tb||'.'||vv_changcol||' '||vv_changcol||vv_rncnt;
else
vv_sql1_mid := vv_sql1_mid||','||tb||'.'||vv_changcol||' '||vv_changcol||vv_rncnt;
end if;
vv_colcnt := vv_colcnt+1;
end loop;
vv_sql1 := 'select '||tb||'.'||vv_keycol||','||vv_sql1_mid;
vv_sql2 := 'from (select * from '||vv_username||'.'||vv_tabtmp||' where rn = '||vv_rncnt||') '||tb;
else
vv_colcnt := 1;
vv_sql1_mid := null;
while( vv_colcnt <= vv_changcolcnt ) loop
/*拆分横向字段串*/
if( vv_colcnt < vv_changcolcnt ) then
if( vv_colcnt = 1 ) then
vv_changcol := substr(upper(trim(vv_changcollist)),1,instr(trim(vv_changcollist),',',1,vv_colcnt)-1);
else
vv_changcol := substr(upper(trim(vv_changcollist)),instr(trim(vv_changcollist),',',1,vv_colcnt-1)+1,instr(trim(vv_changcollist),',',1,vv_colcnt)-instr(trim(vv_changcollist),',',1,vv_colcnt-1)-1);
end if;
else
/*最后一个字段时处理*/
if( vv_changcolcnt = 1 ) then
vv_changcol := substr(upper(trim(vv_changcollist)),1);
else
vv_changcol := substr(upper(trim(vv_changcollist)),instr(trim(vv_changcollist),',',1,vv_changcolcnt-1)+1);
end if;
end if;

if( vv_sql1_mid is null ) then
vv_sql1_mid := 'case when '||tb||'.'||vv_keycol||' is not null then '||tb||'.'||vv_changcol||' end '||vv_changcol||vv_rncnt;
else
vv_sql1_mid := vv_sql1_mid||',case when '||tb||'.'||vv_keycol||' is not null then '||tb||'.'||vv_changcol||' end '||vv_changcol||vv_rncnt;
end if;
vv_colcnt := vv_colcnt+1;
end loop;

vv_sql1 := vv_sql1||','||vv_sql1_mid;
vv_sql2 := vv_sql2||','||'(select * from '||vv_username||'.'||vv_tabtmp||' where rn = '||vv_rncnt||') '||tb;
if ( vv_sql3 is null ) then
vv_sql3 := 'where tb1.'||vv_keycol||' = '||tb||'.'||vv_keycol||'(+)';
else
vv_sql3 := vv_sql3||' and tb1.'||vv_keycol||' = '||tb||'.'||vv_keycol||'(+)';
end if;
end if;
vv_rncnt := vv_rncnt+1;
end loop;

if ( vv_sql1 is not null and vv_sql2 is not null ) then
vv_sql := 'create table '||vv_username||'.'||vv_tabrsl||' nologging as '||vv_sql1||' '||vv_sql2||' '||vv_sql3;
end if;
else
/*无横向字段,只去重处理*/
vv_sql := 'create table '||vv_username||'.'||vv_tabrsl||' nologging as select distinct '||vv_keycol||' from '||vv_username||'.'||vv_tabname;
end if;
end;

/*横向数据表生成*/
begin
--return(vv_sql);
execute immediate 'select count(1) from all_tables where table_name = '''||vv_tabrsl||''' and owner = '''||vv_username||'''' into vv_ifexists_tab;
if ( vv_ifexists_tab > 0 ) then
execute immediate 'truncate table '||vv_username||'.'||vv_tabrsl;
execute immediate 'drop table '||vv_username||'.'||vv_tabrsl||' purge';
end if;
  execute immediate vv_sql;
execute immediate 'select count(1) from all_tables where table_name = '''||vv_tabtmp||''' and owner = '''||vv_username||'''' into vv_ifexists_tab;
if ( vv_ifexists_tab > 0 ) then
execute immediate 'truncate table '||vv_username||'.'||vv_tabtmp;
execute immediate 'drop table '||vv_username||'.'||vv_tabtmp||' purge';
end if;
end;
  /*返回最终结果表*/
Result := '返回处理后结果表:'||vv_username||'.'||vv_tabrsl;
return(Result);
  end f_table_change;

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-255497-1-1.html 上篇帖子: oracle批量添加修改,传List方式 下篇帖子: Oracle用游标分解号码次数
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表