楼主: 〇〇

[精华] 计划用PL/SQL做一个SQL生成器(更新在20/27楼)

[复制链接]
论坛徽章:
15
2010新春纪念徽章
日期:2010-03-01 11:19:492015年新春福章
日期:2015-03-06 11:58:18暖羊羊
日期:2015-03-06 10:26:33美羊羊
日期:2015-03-04 14:52:28优秀写手
日期:2014-06-25 06:00:12ITPUB 11周年纪念徽章
日期:2012-10-10 13:11:142011新春纪念徽章
日期:2011-03-07 09:37:172011新春纪念徽章
日期:2011-02-18 11:43:362010广州亚运会纪念徽章:保龄球
日期:2010-11-11 17:57:122010广州亚运会纪念徽章:田径
日期:2010-11-11 17:57:05
21#
发表于 2010-8-6 16:20 | 只看该作者
呵呵  sql生成器  这名字牛了

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
22#
 楼主| 发表于 2010-8-6 20:46 | 只看该作者
下步准备让列方向支持〉2列,用空格隔开的列串做参数

使用道具 举报

回复
论坛徽章:
74
蓝锆石
日期:2011-12-29 15:35:34萤石
日期:2011-11-18 15:00:15祖母绿
日期:2011-12-29 15:26:07海蓝宝石
日期:2011-12-30 16:00:25紫水晶
日期:2011-12-29 15:26:07红宝石
日期:2011-12-29 15:26:07季节之章:冬
日期:2012-01-01 12:35:07季节之章:冬
日期:2012-01-01 12:35:07季节之章:夏
日期:2011-09-28 16:06:59季节之章:夏
日期:2011-09-28 16:06:59
23#
发表于 2010-8-7 11:11 | 只看该作者
期待中 回去测一下

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
24#
 楼主| 发表于 2010-8-7 20:48 | 只看该作者
饱受单引号折磨后出来的半成品

create or replace function
fsql1(v_tname varchar,tr  varchar ,tc0 varchar,v_tcode varchar)
return varchar
is
tc varchar(4000);
sqlstr varchar(4000);
s1 varchar(4000);
s2 varchar(4000);
s3 varchar(4000);
s4 varchar(4000);
TYPE rc IS REF CURSOR;
TYPE nlist IS TABLE OF NUMBER;
TYPE vlist IS TABLE OF VARCHAR2(400);
rc1 rc;
g1  vList;
g2  vList;
g3  vList;   

begin
tc:=' '||trim(tc0)||' ';
s1:='with t
as (select '||tr||','||replace(trim(tc),' ',',')||',count(*) cnt from tren group by '||tr||','||replace(trim(tc),' ',',')||')';

sqlstr:='select l,substr(tc,instr(tc,'' '',1,l)+1,instr(tc,'' '',1,l+1)-instr(tc,'' '',1,l)-1) pos
from (select '''||tr||'''tr,'''||tc||''' from dual)t,(select level l from dual connect by level<=10)a where l<length(tc)-length(replace(tc,'' '',''''))';
sqlstr:=replace(sqlstr,'tc',''''||tc||'''');
   OPEN rc1 FOR sqlstr;
   FETCH rc1 BULK COLLECT INTO g1, g2;
   CLOSE rc1;
   FOR i IN g1.FIRST ..g1.LAST
   LOOP
   if i>1 then
    s2:=s2||' and ';
  end if;
   s2:=s2||chr(96+i)||'.cname='''||g2(i)||'''';
   END LOOP;
return s1||chr(10)||replace(s2,'tc',''''||tc||'''');
end;
/
select fsql1('a','region','sex nation age class teacher grade','eav')from dual;

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
25#
 楼主| 发表于 2010-8-8 07:19 | 只看该作者
其实用过程语言拆分字符串更方便,昨天糊涂了

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
26#
 楼主| 发表于 2010-8-9 11:05 | 只看该作者
在20楼基础上

insert into eav select 'tren','nation',NULL,'民族' from dual;
insert into eav select 'tren','nation','1','汉' from dual;
insert into eav select 'tren','nation','2','壮' from dual;

insert into eav select 'tren','class1',NULL,'民族' from dual;
insert into eav select 'tren','class1','1','学生' from dual;
insert into eav select 'tren','class1','2','工人' from dual;
insert into eav select 'tren','class1','3','农民' from dual;

alter table tren add nation varchar(2);

alter table tren add class1 varchar(2);

update tren set nation=mod(abs(dbms_random.random),2)+1,class1=mod(abs(dbms_random.random),3)+1;






create or replace function
fsql1(v_tname varchar,tr  varchar ,tc0 varchar,v_tcode varchar)
return varchar
is
tc varchar(4000);
sqlstr varchar(4000);
s1 varchar(4000);
s2 varchar(4000);
s3 varchar(4000);
s4 varchar(4000);
TYPE rc IS REF CURSOR;
TYPE nlist IS TABLE OF NUMBER;
TYPE vlist IS TABLE OF VARCHAR2(400);
rc1 rc;
g1  vList;
g2  vList;
g3  vList;   

begin
tc:=' '||trim(tc0)||' ';
s1:='with t
as (select '||tr||','||replace(trim(tc),' ',',')||',count(*) cnt from '|| v_tname||' group by '||tr||','||replace(trim(tc),' ',',')||')';

sqlstr:='select l,substr(tc,instr(tc,'' '',1,l)+1,instr(tc,'' '',1,l+1)-instr(tc,'' '',1,l)-1) pos
from (select '''||tr||'''tr,'''||tc||''' from dual)t,(select level l from dual connect by level<=10)a where l<length(tc)-length(replace(tc,'' '',''''))';
sqlstr:=replace(sqlstr,'tc',''''||tc||'''');
s3:='select ''sum(case when ''';
   OPEN rc1 FOR sqlstr;
   FETCH rc1 BULK COLLECT INTO g1, g2;
   CLOSE rc1;
   FOR i IN g1.FIRST ..g1.LAST
   LOOP
   if i>1 then
   s2:=s2||',';
   s3:=s3||''' and ''';
  end if;
   s2:=s2||'(select * from '||v_tcode||' where cname='''||g2(i)||''' and ccode is not null)'||chr(96+i)||chr(10); --拼凑where
   --(a)sqlstr:=q'[select 'sum(case when '||a.cname||'='''||a.ccode||''' and '||b.cname||'='''||b.ccode||''' then cnt end)as c'|| a.cname2||b.cname2
   --(b)sum(case when sex='M' and age='1' then cnt end)as c男1岁
   s3:=s3||'||'||chr(96+i)||'.cname||''=''''''||'||chr(96+i)||'.ccode||'||'''''' ; --拼凑case when语句,拼出(a),运行得(b)
   s4:=s4||case i when 1 then'c''||'else'||'end||chr(96+i)||'.cname2'; --拼凑别名
   END LOOP;
sqlstr:=s3||''' then cnt end) as '||s4||'
from '||replace(s2,'tc',''''||tc||'''');
s2:='';
s4:='SELECT cname,ccode,cname2 FROM '||v_tcode||' WHERE tname=:1 and cname=:2';
   OPEN rc1 FOR s4 USING v_tname,tr;
   FETCH rc1 BULK COLLECT INTO g1, g2,g3;
   CLOSE rc1;
   FOR i IN g1.FIRST ..g1.LAST
   LOOP
   if g1(i)=tr and g2(i)is null then
   s2:='
,t1 as(select '||tr||' as '||g3(i)||chr(10);
   end if;
   END LOOP;
if s2 is null then
        return 'error';
end if;

OPEN rc1 FOR sqlstr;
   FETCH rc1 BULK COLLECT INTO g1;
   CLOSE rc1;
   FOR i IN g1.FIRST ..g1.LAST
   LOOP
   s2:=s2||','||g1(i)||chr(10);
   END LOOP;
s3:='group by '||tr;
return s1||s2||'from t '||s3||')
select * from t1';
end;
/
--select fsql1('tren','region','sex age','eav') from dual;
select fsql1('tren','region','sex nation age class1','eav')from dual;

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
27#
 楼主| 发表于 2010-8-9 11:15 | 只看该作者


SQL> with t
  2  as (select class1,sex,nation,age,region,count(*) cnt from tren group by class1,sex,nation,age,region)
  3  ,t1 as(select class1 as 民族
  4  ,sum(case when sex='M' and nation='1' and age='1' and region='1' then cnt end) as c男汉1岁北京
  5  ,sum(case when sex='M' and nation='1' and age='1' and region='2' then cnt end) as c男汉1岁天津
  6  ,sum(case when sex='M' and nation='1' and age='2' and region='1' then cnt end) as c男汉2岁北京
  7  ,sum(case when sex='M' and nation='1' and age='2' and region='2' then cnt end) as c男汉2岁天津
  8  ,sum(case when sex='F' and nation='1' and age='1' and region='1' then cnt end) as c女汉1岁北京
  9  ,sum(case when sex='F' and nation='1' and age='1' and region='2' then cnt end) as c女汉1岁天津
10  ,sum(case when sex='F' and nation='1' and age='2' and region='1' then cnt end) as c女汉2岁北京
11  ,sum(case when sex='F' and nation='1' and age='2' and region='2' then cnt end) as c女汉2岁天津
12  ,sum(case when sex='M' and nation='2' and age='1' and region='1' then cnt end) as c男壮1岁北京
13  ,sum(case when sex='M' and nation='2' and age='1' and region='2' then cnt end) as c男壮1岁天津
14  ,sum(case when sex='M' and nation='2' and age='2' and region='1' then cnt end) as c男壮2岁北京
15  ,sum(case when sex='M' and nation='2' and age='2' and region='2' then cnt end) as c男壮2岁天津
16  ,sum(case when sex='F' and nation='2' and age='1' and region='1' then cnt end) as c女壮1岁北京
17  ,sum(case when sex='F' and nation='2' and age='1' and region='2' then cnt end) as c女壮1岁天津
18  ,sum(case when sex='F' and nation='2' and age='2' and region='1' then cnt end) as c女壮2岁北京
19  ,sum(case when sex='F' and nation='2' and age='2' and region='2' then cnt end) as c女壮2岁天津
20  from t group by class1)
21  select * from t1;

民 C男汉1岁北京 C男汉1岁天津 C男汉2岁北京 C男汉2岁天津 C女汉1岁北京 C女汉1岁天津 C女汉2岁北京 C女汉2岁天津 C男壮1岁北京 C男壮1岁天津
-- ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------
C男壮2岁北京 C男壮2岁天津 C女壮1岁北京 C女壮1岁天津 C女壮2岁北京 C女壮2岁天津
------------ ------------ ------------ ------------ ------------ ------------
1            24           27           21           15           20           14           30        17      25           25
          21           26           15           19           12           24

3            22           23           18           16           15           29           18        15      25           18
          26           24           18           23           17           20

2            18           19           22           24           18           24           17        23      12           30
          28           19           16           16           29           23

使用道具 举报

回复
论坛徽章:
8
数据库板块每日发贴之星
日期:2009-06-12 01:01:02数据库板块每日发贴之星
日期:2009-06-21 01:01:01ITPUB9周年纪念徽章
日期:2010-10-08 09:32:272010广州亚运会纪念徽章:游泳
日期:2010-11-12 16:42:092011新春纪念徽章
日期:2011-02-18 11:42:502010广州亚运会纪念徽章:三项全能
日期:2011-02-26 13:07:50咸鸭蛋
日期:2011-08-30 15:51:05ITPUB十周年纪念徽章
日期:2011-11-01 16:25:22
28#
发表于 2010-8-9 15:37 | 只看该作者

这得要多深的功夫咧!顶啊@

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
29#
 楼主| 发表于 2010-8-10 14:49 | 只看该作者
专门为不带汇总的行列转换写了一个

create or replace function
fsql2(v_tname varchar,tr  varchar ,tc0 varchar,v_tcode varchar)
return varchar
is
tc varchar(4000);
sqlstr varchar(4000);
s1 varchar(4000);
s2 varchar(4000);
s3 varchar(4000);
s4 varchar(4000);
TYPE rc IS REF CURSOR;
TYPE nlist IS TABLE OF NUMBER;
TYPE vlist IS TABLE OF VARCHAR2(400);
rc1 rc;
g1  vList;
g2  vList;
g3  vList;   

begin
tc:=' '||trim(tc0)||' ';
s1:='with t
as (select '||tr||','||replace(trim(tc),' ',',')||',count(*) cnt from '|| v_tname||' group by '||tr||','||replace(trim(tc),' ',',')||')';

sqlstr:='select l,substr(tc,instr(tc,'' '',1,l)+1,instr(tc,'' '',1,l+1)-instr(tc,'' '',1,l)-1) pos
from (select '''||tr||'''tr,'''||tc||''' from dual)t,(select level l from dual connect by level<=10)a where l<length(tc)-length(replace(tc,'' '',''''))';
sqlstr:=replace(sqlstr,'tc',''''||tc||'''');
s3:='select ''min(case when ''';
   OPEN rc1 FOR sqlstr;
   FETCH rc1 BULK COLLECT INTO g1, g2;
   CLOSE rc1;
   FOR i IN g1.FIRST ..g1.LAST-1
   LOOP
   if i>1 then
   s2:=s2||',';
   s3:=s3||''' and ''';
  end if;
   s2:=s2||'(select * from '||v_tcode||' where cname='''||g2(i)||''' and ccode is not null)'||chr(96+i)||chr(10); --拼凑where
   --(a)sqlstr:=q'[select 'sum(case when '||a.cname||'='''||a.ccode||''' and '||b.cname||'='''||b.ccode||''' then cnt end)as c'|| a.cname2||b.cname2
   --(b)sum(case when sex='M' and age='1' then cnt end)as c男1岁
   s3:=s3||'||'||chr(96+i)||'.cname||''=''''''||'||chr(96+i)||'.ccode||'||'''''' ; --拼凑case when语句,拼出(a),运行得(b)
   s4:=s4||case i when 1 then'c''||'else'||'end||chr(96+i)||'.cname2'; --拼凑别名
   END LOOP;
sqlstr:=s3||''' then '||g2(g1.LAST)||' end) as '||s4||'
from '||replace(s2,'tc',''''||tc||'''');
s2:='';
s4:='SELECT cname,ccode,cname2 FROM '||v_tcode||' WHERE tname=:1 and cname=:2';
   OPEN rc1 FOR s4 USING v_tname,tr;
   FETCH rc1 BULK COLLECT INTO g1, g2,g3;
   CLOSE rc1;
   FOR i IN g1.FIRST ..g1.LAST
   LOOP
   if g1(i)=tr and g2(i)is null then
   s2:='
,t1 as(select '||tr||' as '||g3(i)||chr(10);
   end if;
   END LOOP;
if s2 is null then
        return 'error';
end if;
--return sqlstr;
OPEN rc1 FOR sqlstr;
   FETCH rc1 BULK COLLECT INTO g1;
   CLOSE rc1;
   FOR i IN g1.FIRST ..g1.LAST
   LOOP
   s2:=s2||','||g1(i)||chr(10);
   END LOOP;
s3:='group by '||tr;
return s1||s2||'from t '||s3||')
select * from t1';
end;
/

create table faq(ID varchar(10),NAME varchar(10),VALUE varchar(10));
insert into faq select * from (
select'1'id,'a1'name,'x1'value from dual union all
select'1','a2','x2'from dual union all
select'2','b1','y1'from dual union all
select'2','b2','y2'from dual union all
select'2','b3','y3'from dual);
commit;
insert into eav values('FAQ','ID',NULL,'ID');
insert into eav select 'FAQ','ID',ID,ID from dual,(select unique id from faq);

insert into eav values('FAQ','NAME',NULL,'NAME');
insert into eav select 'FAQ','NAME',NAME,NAME from dual,(select unique NAME from faq);

insert into eav values('FAQ','VALUE',NULL,'VALUE');
insert into eav select 'FAQ','VALUE',VALUE,VALUE from dual,(select unique VALUE from faq);

commit;




SQL> select fsql2('FAQ','NAME','ID VALUE','eav')from dual;

FSQL2('FAQ','NAME','IDVALUE','EAV')
-------------------------------------------------------------------------------
with t
as (select NAME,ID,VALUE,count(*) cnt from FAQ group by NAME,ID,VALUE)
,t1 as(select NAME as NAME
,min(case when ID='1' then VALUE end) as c1
,min(case when ID='2' then VALUE end) as c2
from t group by NAME)
select * from t1


已用时间:  00: 00: 00.01
SQL> with t
  2  as (select NAME,ID,VALUE,count(*) cnt from FAQ group by NAME,ID,VALUE)
  3  ,t1 as(select NAME as NAME
  4  ,min(case when ID='1' then VALUE end) as c1
  5  ,min(case when ID='2' then VALUE end) as c2
  6  from t group by NAME)
  7  select * from t1;

NAME       C1         C2
---------- ---------- ----------
a1         x1
b2                    y2
a2         x2
b1                    y1
b3                    y3

使用道具 举报

回复
论坛徽章:
1088
金色在线徽章
日期:2007-04-25 04:02:08金色在线徽章
日期:2007-06-29 04:02:43金色在线徽章
日期:2007-03-11 04:02:02在线时间
日期:2007-04-11 04:01:02在线时间
日期:2007-04-12 04:01:02在线时间
日期:2007-03-07 04:01:022008版在线时间
日期:2010-05-01 00:01:152008版在线时间
日期:2011-05-01 00:01:342008版在线时间
日期:2008-06-03 11:59:43ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30
30#
发表于 2010-8-10 15:58 | 只看该作者
不错,研究一下!

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表