亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Oracle集合類(lèi)型輸出參數(shù)的PL/SQL存儲(chǔ)過(guò)程及其Ja

系統(tǒng) 2768 0

現(xiàn)在的java的數(shù)據(jù)庫(kù)-關(guān)系映射技術(shù)似乎不提倡用存儲(chǔ)過(guò)程,其實(shí)存儲(chǔ)過(guò)程更能發(fā)揮數(shù)據(jù)庫(kù)的效率。
1? 引言
存儲(chǔ)過(guò)程因其執(zhí)行效率高、與事務(wù)處理的結(jié)合、運(yùn)行更安全等優(yōu)點(diǎn),在數(shù)據(jù)庫(kù)應(yīng)用程序中被廣泛采用。PL/SQL是用于從各種環(huán)境中訪問(wèn)Oracle數(shù)據(jù)庫(kù)的一種編程語(yǔ)言,它與數(shù)據(jù)庫(kù)服務(wù)器集成在一起,PL/SQL編寫(xiě)的存儲(chǔ)過(guò)程編譯效率高,網(wǎng)絡(luò)系統(tǒng)開(kāi)銷(xiāo)小,同時(shí)PL/SQL直觀性好,是大多數(shù)人的選擇。
以Number、Varchar等基本標(biāo)量類(lèi)型為輸出參數(shù)的PL/SQL存 儲(chǔ)過(guò)程,每個(gè)輸出參數(shù)只能返回一個(gè)對(duì)應(yīng)值。而在實(shí)際數(shù)據(jù)庫(kù)應(yīng)用程序中,尤其是在進(jìn)行系統(tǒng)綜合查詢(xún)統(tǒng)計(jì)時(shí),往往需要返回二維數(shù)組或結(jié)果集,這時(shí)應(yīng)考慮在存儲(chǔ) 過(guò)程中使用集合這種數(shù)據(jù)結(jié)構(gòu)。對(duì)于集合,我們可以一次把許多元素作為一個(gè)整體進(jìn)行操作,也可以對(duì)集合中的單個(gè)元素進(jìn)行操作,使用方便、靈活。
?
2? PL/SQL存儲(chǔ)過(guò)程及Java程序的編寫(xiě)
2.1??索引表作為輸出參數(shù)

      索引表是無(wú)約束的,其大小的唯一限制(除可用內(nèi)存外)就是它的關(guān)鍵字BINARY_INTEGER類(lèi)型所能表示數(shù)值的約束(-2147483647...+2147483647),其元素不需要按任何特定順序排列。在聲明時(shí),我們不需要指定其大小,而且對(duì)索引表的元素可以直接賦值,不用初始化,可見(jiàn)使用索引表極其方便。

    

2.1.1 存儲(chǔ)過(guò)程的編寫(xiě)
我們可以在PL/SQL語(yǔ)句塊中定義索引表,但作為輸出參數(shù)的索引表,必須要在包(package)里定義,方法如下:
create or replace package out_param is?????????????????????????????????????????
----?定義了元素是varchar2類(lèi)型的一個(gè)索引表類(lèi)型
type out_index_table_typ is table of varchar2(50) index by binary_integer;
end out_param;
接下來(lái)就可以在pl/sql存儲(chǔ)過(guò)程里引用在包里定義的索引表類(lèi)型:
????????????????? ?create or replace procedure testPro1(in_param in varchar2,o_table out? out_param. out_index_table_typ ) is
????????????????????? begin?
????????????????? ????????-------這里略去程序體
????????????????????? end? testPro1;?
??????????其中,返回的索引表類(lèi)型前必須用包名加上句點(diǎn)來(lái)引用out_param. out_index_table_typ?
2.1.2? J ava程序的編寫(xiě)
索引表與數(shù)據(jù)庫(kù)表很形似,有key和value兩列,但它不是真正的數(shù)據(jù)庫(kù)表,不可以存儲(chǔ)到數(shù)據(jù)庫(kù)中。因此索引表不能使用SQL進(jìn)行操作,這樣它的內(nèi)容不能通過(guò)一個(gè)標(biāo)準(zhǔn)的SELECT語(yǔ)句返回游標(biāo)得到。這一點(diǎn)與嵌套表有很大不同。由存儲(chǔ)過(guò)程返回的索引表可以映射成java數(shù)組類(lèi)型、 JDBC Datatypes的 BigDecimal[]數(shù)組類(lèi)型和oracle的Datum[]數(shù)組。有一點(diǎn)要注意,盡管索引表中的元素不一定要按任何特定順序排列,其元素可以借助于任意有效關(guān)鍵字而插入,但對(duì)映射數(shù)組元素的引用應(yīng)該從1開(kāi)始,而且要連續(xù),否則映射成數(shù)組時(shí)會(huì)出現(xiàn)null元素。
下面示例為將索引表映射成java數(shù)組類(lèi)型。

Java代碼?? 收藏代碼
  1. import ?oracle.jdbc.*;??
  2. import ?oracle.sql.*;??
  3. import ?java.sql.*;??
  4. public ? class ?ReturnIndexTable??
  5. {??Connection?ociconn= null ;??
  6. OracleCallableStatement?stmt?= null ;??
  7. public ?String[]?getTable(String?in_param)??
  8. {??String[]?reAry= null ;??
  9. try ??
  10. {??OracleDriver?S_Driver= null ;??
  11. if (S_Driver== null )??
  12. S_Driver= new ?oracle.jdbc.OracleDriver();??
  13. DriverManager.registerDriver(S_Driver);??
  14. String?url= "jdbc:oracle:oci8:@test" ;??
  15. String?user= "user" ;??
  16. String?password= "?password" ;??
  17. ociconn=?DriverManager.getConnection(url,user,password);??
  18. stmt?=(OracleCallableStatement)ociconn.prepareCall( "begin?testPro1(?,?);?end;" );??
  19. //?返回的索引表最大長(zhǎng)度(可以大于索引表實(shí)際長(zhǎng)度) ??
  20. int ??maxLen?= 31 ;??
  21. //?索引表元素類(lèi)型 ??
  22. int ??elemSqlType?=?OracleTypes.VARCHAR;??
  23. //索引表元素長(zhǎng)度(CHAR,?VARCHAR?or?RAW),其它元素類(lèi)型可忽略該項(xiàng)值,但該參數(shù)仍須定義 ??
  24. int ??elemMaxLen= 50 ;??
  25. stmt.setString( 1 ,in_param);??
  26. //?注冊(cè)返回參數(shù) ??
  27. stmt.registerIndexTableOutParameter( 2 ,maxLen,elemSqlType,elemMaxLen);??
  28. stmt.execute();??
  29. //?返回?cái)?shù)組類(lèi)型 ??
  30. reAry=(String[])stmt.getPlsqlIndexTable( 2 );??
  31. }??
  32. catch ?(Exception?e)??
  33. {e.printStackTrace();??
  34. }??
  35. finally ??
  36. { return ?reAry;??
  37. }??
  38. }??
  39. //關(guān)閉連接............. ??
  40. }??

? 2.2??可變數(shù)組作為輸出參數(shù)

????????? ?可變數(shù)組和另外兩種集合類(lèi)型不同,其元素在內(nèi)存中是連續(xù)存儲(chǔ)的,且在大小方面有一個(gè)固定的上界。聲明時(shí)需要指定該數(shù)組中元素的最大數(shù)目(可變數(shù)組的大小可以用EXTEND方法來(lái)增加,但不能被擴(kuò)展超過(guò)所聲明的極限大?。?。

可變數(shù)組的元素被賦值之前,必須使用構(gòu)造器進(jìn)行初始化。元素插入數(shù)組時(shí)應(yīng)從索引1開(kāi)始,連續(xù)插入。
2.2.1 ?存儲(chǔ)過(guò)程的編寫(xiě)
可變數(shù)組的定義方法如下:
create or replace type testArray is varray(5) of number(3)
???????? PL/SQL存儲(chǔ)過(guò)程里調(diào)用可變數(shù)組作為輸出參數(shù):
create or replace function getTestArray return testArray
as
???o_data testArray:= testArray (); ?
begin
??? for v_count in 1..5 loop
????? o_data.extend;?
????? o_data(v_count):= v_count;
??? end loop;
???return o_data;
end;?
2.2.2? J ava程序的編寫(xiě)
???????? 由存儲(chǔ)過(guò)程返回的可變數(shù)組同樣可以映射成java數(shù)組類(lèi)型。但Java程序調(diào)用存儲(chǔ)過(guò)程返回的可變數(shù)組方式和索引表方式卻不相同,這一點(diǎn)應(yīng)注意,具體方法如下:
public static void main( )?
{
......
//調(diào)用存儲(chǔ)過(guò)程
.????????? ?OracleCallableStatement stmt =(OracleCallableStatement)conn.prepareCall ( "begin ? := getTestArray; end;" );????
?? ??????????stmt.registerOutParameter( 1, OracleTypes.ARRAY,"?testArray" );
? ??????????stmt.executeUpdate();
?? ?????????// 得到 ARRAY 對(duì)象
?? ????????? ARRAY simpleArray = stmt.getARRAY(1);
//轉(zhuǎn)換為java數(shù)組
? ?????????? String[ ] values = (String[])simpleArray.getArray();
//輸出數(shù)組內(nèi)容
?? ?????????for( int i = 0; i < values.length; i++ )
??? ?????????System.out.println( "row " + i + " = '" + values[i] +"'" );
}
2.3??嵌套表作為輸出參數(shù)
存 儲(chǔ)過(guò)程中使用嵌套表,并不是直接將嵌套表作為輸出參數(shù),而是對(duì)嵌套表"造型"后以游標(biāo)形式輸出。嵌套表的基本功能與索引表相同,但嵌套表可以使用SQL進(jìn) 行操作,其內(nèi)容可通過(guò)SELECT 語(yǔ)句查詢(xún)并"造型"后以游標(biāo)形式返回。在大多數(shù)的查詢(xún)統(tǒng)計(jì)中,常常需要返回結(jié)果集,這時(shí)使用嵌套表就尤其方便。筆者在開(kāi)發(fā)過(guò)程中深刻體會(huì)到使用對(duì)象嵌套表 可以解決絕大多數(shù)的查詢(xún)統(tǒng)計(jì)問(wèn)題。下面著重介紹如何在存儲(chǔ)過(guò)程里利用對(duì)象類(lèi)型的嵌套表。
對(duì)于任意的統(tǒng)計(jì)分析表格,我們可以將其簡(jiǎn)化成下面的輸出形式:

??? ??????統(tǒng)計(jì)項(xiàng)目1 統(tǒng)計(jì)項(xiàng)目2 統(tǒng)計(jì)項(xiàng)目3 統(tǒng)計(jì)項(xiàng)目4
名稱(chēng)1 ? ? ? ?
名稱(chēng)2 ? ? ? ?

這樣我們把每一行看作是一個(gè)對(duì)象實(shí)例,該行的每一列則可以看作是該對(duì)象的一個(gè)屬性,下面通過(guò)構(gòu)造對(duì)象,然后對(duì)包含對(duì)象的嵌套表進(jìn)行造型,返回游標(biāo)得到結(jié)果集。
?2.3.1? 存儲(chǔ)過(guò)程的編寫(xiě)
??首先構(gòu)造統(tǒng)計(jì)對(duì)象如下:
????? create or replace type TestObj as object
(?
?vname? varchar2(20),??? --名稱(chēng)
?item1?? number,??????? --統(tǒng)計(jì)項(xiàng)目1
?item2?? number,??????? --統(tǒng)計(jì)項(xiàng)目2
?item3?? number,??????? --統(tǒng)計(jì)項(xiàng)目3
item4?? number??????? --統(tǒng)計(jì)項(xiàng)目4
);
構(gòu)造包含對(duì)象類(lèi)型的嵌套表:
?create or replace type TestNestTable as table of TestObj;
定義對(duì)索引表"造型"后的輸出的游標(biāo)類(lèi)型:
create or replace package out_param is?
type out_cur is ref cursor;?????????
下面是嵌套表作為輸出參數(shù)的存儲(chǔ)過(guò)程:
create or replace procedure testPro2(o_cur out out_param.out_cur ) is
----?包含對(duì)象的嵌套表變量的聲明
v_objTable? TestNestTable:= TestNestTable ();
begin
???????????????????? --嵌套表變量的使用
v_objTabl.extend;
v_objTable(1):= TestObj(‘張三',12,123,123,34);
v_objTabl.extend;
v_objTable(2):= TestObj(‘李四,22,223,223,234);
--對(duì)嵌套表進(jìn)行"造型"返回游標(biāo)
open? o_cur? for??select * from Table(cast (v_objTable?as?TestNestTable) );?
end ?testPro2;
2.3.2? J ava程序的編寫(xiě)
???? //從游標(biāo)返回結(jié)果集
public ResultSet getCursor()
{
try
{
......
stmt =(CallableStatement )conn.prepareCall("call testPro2(?)");
//注冊(cè)游標(biāo)對(duì)象類(lèi)型
stmt.registerOutParameter(1,OracleTypes.CURSOR);
stmt.execute();
//返回結(jié)果集
ResultSet ?Rs=(ResultSet)stmt.getObject(1);
}
catch(Exception e)
{
}
return Rs;
}
3??結(jié)束語(yǔ)
使用索引表和可變數(shù)組,可將返回的集合映射成Java數(shù)組。由于索引表會(huì)自動(dòng)分配空間,在聲明時(shí)不需要指定其大小,而且不需要初始化,使用起來(lái)比較方便。但是索引表作為輸出參數(shù)只能使用oci驅(qū)動(dòng)(返回游標(biāo)時(shí),可以用瘦客戶(hù)驅(qū)動(dòng)也可以用oci驅(qū)動(dòng)),所需要的動(dòng)態(tài)連接庫(kù)文件(ocijdbc9.dll)要在環(huán)境變量里進(jìn)行設(shè)置(例如:path=D:\oracle\ora90\BIN),在不同的環(huán)境下OCI驅(qū)動(dòng)還可能出現(xiàn)類(lèi)裝載異常,所以返回索引表盡管方便,但偶爾會(huì)出現(xiàn)意想不到的錯(cuò)誤??勺償?shù)組映射成Java數(shù)組簡(jiǎn)單,對(duì)于返回小數(shù)據(jù)量的結(jié)果,也是不錯(cuò)的選擇,但使用可變數(shù)組作為輸出參數(shù),聲明時(shí)必須限定該數(shù)組的大小上限,并且需使用構(gòu)造器初始化。
使用嵌套表,可以對(duì)嵌套表進(jìn)行SQL操作,其內(nèi)容能通過(guò)對(duì)標(biāo)準(zhǔn)的SELECT?語(yǔ)句造型后可轉(zhuǎn)化為游標(biāo)輸出。而且嵌套表的內(nèi)容相當(dāng)于session變量,當(dāng)斷開(kāi)連接后即釋放內(nèi)存,但同樣存在需要初始化和擴(kuò)展的問(wèn)題。
綜 上所述,究竟采用索引表、嵌套表和可變數(shù)組中哪一種作為存儲(chǔ)過(guò)程的輸出要看具體的要求和開(kāi)發(fā)環(huán)境。有一點(diǎn)我們需要注意,如果返回的數(shù)據(jù)量較大,以數(shù)組形式 返回,則需一次性取回所有結(jié)果,在PL/SQL里為所有結(jié)果分配空間并復(fù)制,然后將這些數(shù)據(jù)通過(guò)網(wǎng)絡(luò)發(fā)送到客戶(hù)端,客戶(hù)端也同樣需要分配空間接受這些數(shù) 據(jù);而采用游標(biāo)形式,只要返回一個(gè)指針,然后分批返回結(jié)果(可自定義每次返回記錄的條數(shù)),而不是一次性返回所有結(jié)果,因此在客戶(hù)端不需分配大塊的空間存 放所有結(jié)果??梢?jiàn),對(duì)于大數(shù)據(jù)量的應(yīng)用程序,返回游標(biāo)程序運(yùn)行效率會(huì)更高。


Oracle集合類(lèi)型輸出參數(shù)的PL/SQL存儲(chǔ)過(guò)程及其Java調(diào)用


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦?。?!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 伊人高清视频 | 久草欧美视频 | 成人免费播放视频777777 | 国产码欧美日韩高清综合一区 | 色久综合网 | 狠狠色综合久久婷婷 | 亚洲视频在线观看不卡 | 亚洲第一成年网 | 欧美精品一区二区三区视频 | 伊人免费视频 | 国产高清免费视频 | 亚洲精品国产一区二区三区在 | 久久久视频6r | 久久综合久色欧美婷婷 | 青草社区| jizz成熟丰满老女人 | 网曝门精品国产事件在线观看 | 国产成人a∨麻豆精品 | 亚洲精品第一国产综合高清 | 女人18毛片a级毛片免费看一 | 东北一级毛片 | 狠狠操夜夜操 | 国产精品美女一级在线观看 | 国内精品小视频在线 | 天天草夜夜骑 | 尤物视频一区 | 亚洲va欧美va国产va天堂 | 欧美精彩狠狠色丁香婷婷 | 亚洲天堂区 | 青青青国产精品国产精品久久久久 | 91亚洲精品久久91 | 无遮挡一级毛片性视频不卡 | 午夜国产精品久久影院 | 黄频网站在线观看视频 | 日本黄 色 成 年 人免费观看 | 欧美午夜在线视频 | 久久久亚洲精品视频 | 深夜福利免费观看 | 特黄aa级毛片免费视频播放 | 亚洲女人国产香蕉久久精品 | 亚洲小younv另类 |