很多時候,我們需要做一些中國式的報表,例如:我們有一下幾張資料表來表示某大學,對各個省份的招生計畫資訊:
省份資訊表
area_id名稱1
遼寧2吉林3
黑龍江……
專業資訊表
speciality_id
院系名稱
1外語系
2計算機系
3中文系……
招生計畫資訊表
area_id
speciality_id
年度招生人數11
201032
1201053
1201031
2201022
2201053
2201031
3201012
3201043
320105…
………
那麼我們想要統計乙個交叉的報表,統計2023年度,每個專業在各個省份的招生人數,即下面這個交叉統計報表(中國式報表):
本年度各個專業在各個省份的招生計畫資訊
外語系計算機系
中文系遼寧32
1吉林55
4黑龍江33
5………
…
下面我們使用乙個儲存過程來實現此型別的報表統計,由於我們首先需要取得此大學院系資料游標,並通過迴圈此游標生成乙個二次查詢統計的sql語句,此sql在生成之後會十分龐大,可能會超過oracle中varchar2的長度限制(32767)。所以此儲存過程採用dbms_sql.varchar2s字串陣列來實現動態sql。
但是問題又出現了,由於dbms_sql.varchar2s執行動態sql之後無法返回乙個游標,所以當dbms_sql.varchar2s執行sql時我們考慮使用view來完成此功能,也就是說,通過dbms_sql.varchar2s執行之後會生成乙個我們需要的臨時檢視view,然後我們再通過普通的sql去查詢此檢視,並返回游標。具體的儲存過程實現如下:
create
orreplace
procedure p_queryreport(h_tablename
invarchar2 ,
--行表名
h_fieldcode
invarchar2 ,
--行編碼
h_fieldname
invarchar2 ,
--行名稱
h_sqlwhere
invarchar2 ,
--行查詢條件從and開始
l_tablename
invarchar2 ,
--列表名
l_fieldcode
invarchar2 ,
--列編碼
l_fieldname
invarchar2 ,
--列名稱
l_sqlwhere
invarchar2 ,
--列查詢條件
c_tablename
invarchar2 ,
--統計表名
c_sum_fieldcode
invarchar2 ,
--彙總欄位名
c_h_fieldcode
invarchar2 ,
--統計表關聯行編碼
c_l_fieldcode
invarchar2 ,
--統計表關聯列編碼
c_sqlwhere
invarchar2 ,
--統計表查詢條件
resultlist
out sys_refcursor
--返回結果集
) authid current_user
isl_sql
varchar2 (32767);
l_rs sys_refcursor;
l_r_code
varchar2 (32767);
l_r_name
varchar2 (32767);
h_sql
varchar2 (32767);
p_c_sqlwhere
varchar (32767);
------------------------------------------
l_stmt
dbms_sql .varchar2s;
l_cursor
integer
default
dbms_sql .open_cursor;
l_rows
number
default 0;
l_length
number := 0;
i
number := 1;
e
number := 0;
--------------------------------------------
begin
p_c_sqlwhere := c_sqlwhere;
e :=
length (p_c_sqlwhere);
l_stmt(i) :=
'create or replace view lhtempview as select ' ||
h_fieldcode ||
',' || h_fieldname ||
',' ;
i := i + 1;
l_sql :=
'select ' || l_fieldcode ||
',' || l_fieldname ||
' from ' ||
l_tablename ||
' where 1=1 ' || trim(l_sqlwhere) ||
' ' ;
open l_rs
for l_sql;
loop
fetch l_rs
into l_r_code, l_r_name;
exit
when l_rs%notfound;
l_stmt(i) :=
' (select sum(' || c_sum_fieldcode ||
') from ' ;
i := i + 1;
l_stmt(i) := c_tablename;
i := i + 1;
l_stmt(i) :=
' where ' ;
i := i + 1;
l_stmt(i) := c_l_fieldcode;
i := i + 1;
l_stmt(i) :=
' = '
'' || l_r_code ||
''' ' ;
i := i + 1;
l_stmt(i) := trim(p_c_sqlwhere);
i := i + 1;
l_stmt(i) :=
' and ' || c_h_fieldcode ||
' = ' || h_fieldcode ||
') as "' || l_r_name ||
'_' || i ||
'",' ;
i := i + 1;
endloop ;
if i > 2
then
l_stmt(i - 1) :=
substr (l_stmt(i - 1), 0,
length (l_stmt(i - 1)) - 1);
endif ;
l_stmt(i) :=
' from ' || h_tablename ||
' where 1=1 ' || trim(h_sqlwhere);
l_sql := l_stmt(i - 1);
dbms_sql .
parse (c => l_cursor,
statement => l_stmt,
lb => l_stmt.first,
ub => l_stmt.last,
lf*** =>
true ,
language_flag =>
dbms_sql .native);
l_rows :=
dbms_sql .
execute (l_cursor);
dbms_sql .
close_cursor (l_cursor);
h_sql :=
'select * from lhtempview' ;
open resultlist
for h_sql;
end p_queryreport;
利用儲存過程實現資料分頁
利用ms sql2000的儲存過程實現資料分頁讀取,可簡化讀取的資料量。本過程的優點在於,輸入的sql語句沒有限制條件,而且寫法和思路都很簡單明瞭。create procedure dbo pageshow sql varchar 8000 where語句 pagesize int 10,每頁的大小...
oracle儲存過程實現分頁
建立儲存過程 建立存放游標的包 create or replace package page package is 申明游標 type page cursor is ref cursor end page package 建立查詢所有使用者的過程 create or replace procedur...
oracle 儲存過程實現分頁
1 create or replace package pkg query is23 45 author administrator 6 created 2016 12 8 星期四 10 28 37 7 purpose 用做查詢游標89 10 public type declarations 11 ...