“總結(jié)一下本人在項目中遇到的問題,如何在數(shù)據(jù)庫表名未知且作為一種查詢條件的情況下查詢出數(shù)據(jù)集,僅能通過FineReport+Oracle實現(xiàn)。 首先分析這個問題的條件和要求: 條件:只有一個ID,依靠這個ID能查詢出一個數(shù)據(jù)庫表名的集合(表名是通過各種字段拼接起來的) 要求:要遍歷這個數(shù)據(jù)庫表名集合查詢出對應(yīng)的數(shù)據(jù) FineReport即帆軟,可以制作模版,通過傳入變量執(zhí)行模版中的SQL來生成報表。但是我無法將一個數(shù)據(jù)庫表名的集合傳入帆軟模版,這樣只能通過帆軟本身查出數(shù)據(jù)庫表名的集合。在有限的時間里我了解到要實現(xiàn)這樣的功能最直接的方法就是采用Oracle的存儲過程。通過各種百度、摸索最終實現(xiàn)了FineReport調(diào)用存儲過程??偨Y(jié)如下。” 一.存儲過程(參數(shù),變量,游標) 1.測試表:
2.帶參數(shù)的存儲過程 2.1創(chuàng)建一個存儲過程:在Procedures文件夾右鍵New 2.2帶參數(shù)的存儲過程 create or replace procedure test(param1 in varchar2, item out sys_refcursor) as begin open item for select * from TT_CLASS_20160912 tt where tt.length = param1; end; 這里創(chuàng)建的是一個名為“test”的存儲過程,有兩個參數(shù),param1為輸入?yún)?shù),item為輸出參數(shù),從“in”和“out”就可以看出來,“varchar2”和“sys_refcursor”為參數(shù)類型,其中“sys_refcursor”為游標,其實就是一個數(shù)據(jù)集合。 F8執(zhí)行一次就會在Oracle里創(chuàng)建一個存儲過程,實際上是一個編譯過程。
右鍵該存儲過程,點擊“TEST” 填入?yún)?shù),F(xiàn)8執(zhí)行,點擊結(jié)果的小點點就能查看到結(jié)果集了 3.存儲過程的變量 修改存儲過程如下,添加了兩個變量“tableName”和“select_query”,存儲過程的變量和函數(shù)的變量相似,作用于存儲過程體,例子中我把表名和要執(zhí)行的SQL都定義為變量,同2.2執(zhí)行,能看到用存儲過程是有可能解決我的問題。 create or replace procedure test(param1 in varchar2,item out sys_refcursor) as tableName long; select_query long; begin tableName := 'TT_CLASS_20160912'; select_query := 'select * from ' || tableName || ' tt where tt.length = ' || param1 || ''; open item for select_query; end; 4.存儲過程的游標 接下來要解決的問題是,我所需要的表名不是單單一個字符串,而是一個結(jié)果集,我要做的是遍歷這個結(jié)果集進行查詢。這里要用到游標。 修改存儲過程如下,添加了一個變量“flag”和一個游標“myCusor”,這里我簡化了業(yè)務(wù),游標的查詢結(jié)果為兩個表名組成的結(jié)果集?!癴lag”是為了在遍歷游標的時候方便判斷是否為第一條數(shù)據(jù)。 從“declare”開始到“begin”為游標的定義,一般為一個查詢結(jié)果,這里的SQL也是可以用到參數(shù)的。 “open myCusor ... loop”為遍歷游標。 “fetch myCusor into ...”為取值。 整個存儲過程體里的邏輯為:獲取游標結(jié)果集('TT_CLASS_20160912','TT_CLASS_20160922')->遍歷結(jié)果集取出游標里的值賦給變量“tableName”->拼接SQL并執(zhí)行,結(jié)果賦給輸出參數(shù)“item”。 create or replace procedure test(param1 in varchar2, item out sys_refcursor) as flag int; tableName long; select_query long; begin declare cursor myCusor is select table_name from user_tables where table_name = 'TT_CLASS_20160912' or table_name = 'TT_CLASS_20160922'; begin open myCusor; flag := 1; loop fetch myCusor into tableName; exit when myCusor%notfound; if flag = 1 then flag := 0; select_query := 'select * from ' || tableName || ' where length = ' || param1 || ''; else select_query := '' || select_query || 'union (select * from ' || tableName || ' where length = ' || param1 || ')'; end if; end loop; close myCusor; open item for select_query; end; end; 執(zhí)行結(jié)果:成功。當(dāng)然這是在簡化了業(yè)務(wù)的情況下的結(jié)果,但是難點基本都說清楚了?;谶@個方法能夠解決數(shù)據(jù)上的問題了,接下來就是FineReport的使用,畢竟光查出結(jié)果還不夠,還要將結(jié)果用報表顯示出來。 二.FineReport配置 FineReport官網(wǎng):http://www. FineReport在線文檔:http://www.(http://help.) FineReport論壇:http://bbs. 帆軟對版本有一定要求,首先要知道自己服務(wù)器上部署的是什么版本,然后下載對應(yīng)的設(shè)計器,本人用的是7.0 使用帆軟首先要定義數(shù)據(jù)連接,點擊服務(wù)器->定義數(shù)據(jù)連接
填上你的數(shù)據(jù)庫地址、用戶名和密碼,點擊測試連接,成功就說明設(shè)計器的數(shù)據(jù)連接配好了。 需要注意的是設(shè)計器制作的模版文件本身并不包含這些配置信息的,只會存一個連接的名字,比如這里配置的連接名為“test”,在模版文件里只會存“test”,具體信息會去WEB-INF\resource\datasource.xml這個文件里面讀取,所以具體該如何配置數(shù)據(jù)連接可以查看項目里的配置文件。 配置好數(shù)據(jù)連接后,創(chuàng)建數(shù)據(jù)庫查詢,如圖點擊數(shù)據(jù)庫查詢,就可以直接編寫SQL。 這里只寫一些測試用 創(chuàng)建完數(shù)據(jù)庫查詢后會在左側(cè)數(shù)據(jù)集下顯示你的查詢,和對應(yīng)的字段,直接將字段拖入表格即可。 最后點擊預(yù)覽就可以查看報表數(shù)據(jù)了 三.FineReport調(diào)用存儲過程 現(xiàn)在我們有了存儲過程,F(xiàn)ineReport也可以生成報表,要做的就是用FineReport調(diào)用存儲過程,只有簡單一句,如圖 點擊預(yù)覽,看看是否調(diào)用成功,傳一個參數(shù)“2”給它。 有結(jié)果了有木有。 最后我們將結(jié)果集拖入表格,如圖。 另存為模版文件,這樣我們就拿到了能夠調(diào)用存儲過程的FineReport模版。 |
|