del調用返回遊標的存儲過程
一.創建包與包體
1.附:建表aaclass爲下面作測試用
create table aaclass(CID VARCHAR2(50), CNAME VARCHAR2(50), pnumber NUMBER(10,0) );
INSERT INTO aaclass values('c1', 'cn1', 10 ) ;
INSERT INTO aaclass values('c2', 'cn2', 40 ) ;
INSERT INTO aaclass values('c1', 'cn3', 30 ) ;
commit;
2.建包:
CREATE OR REPLACE PACKAGE PKG_JCCTEST1
AS
type rc_class is ref cursor;
--求p1,p2的和與差,返回的多個值通過遊標返回
procedure GetSubAndSum2(p1 number,p2 number ,
ResultCursor out rc_class);
--查詢滿足條件的數據集,返回數據集通過遊標返回
procedure GetClass2(a in number,ResultCursor out rc_class ) ;
--往表中插一條記錄,不返回結果集時,本人用AdoQuery調用(adodataset好象要求必須返回結果集)
procedure InsertClass( p_cid varchar2 ,p_cname varchar2 ,
p_pnumber number) ;
end PKG_JCCTEST1;
3.建包體
CREATE OR REPLACE PACKAGE BODY PKG_JCCTEST1
AS
procedure GetSubAndSum2(p1 number,p2 number ,
ResultCursor out rc_class)
IS
BEGIN
open ResultCursor for
select p1-p2 as "sum", p1+p2 as "sub" from dual;
END ;
procedure GetClass2(a in number,ResultCursor out rc_class )
is
begin
open ResultCursor for
select aaclass.* from aaclass where pnumber >a;
end ;
procedure InsertClass( p_cid varchar2 ,p_cname varchar2 ,
p_pnumber number)
is
begin
insert into aaclass values(p_cid,p_cname,p_pnumber) ;
-- commit;
end ;
二.在delphi中利用AdoDataSet調用上述第一個存儲過程
1.利用AdoConnection1連接數據庫(驅動爲 oracle Provider for OLE DB),
**並在連接字符串中加入這一節: PLSQLRSet=1; 如下所示:
Provider=OraOLEDB.Oracle.1;Password=KXD;Persist Security Info=True;User ID=KXD;Data Source=TEST3;PLSQLRSet=1
2.在窗體上加AdoDataSet1 指明連接爲上述AdoConnection1,下面可以放一個按鈕,單擊按鈕就能調用第一步中創建的包過程,並返回數據集。代碼如下所示:
procedure TForm1.Button1Click(Sender: TObject);
var
AResult , BResult : integer;
begin
ADODataSet1.Close ;
ADODataSet1.CommandType := cmdText ;
ADODataSet1.Parameters.Clear ;
//***利用call方法調用oracle過程時,參數必須由?來傳, 即使你要傳的參數爲常理
//輸出遊標的參數不需要指定!!!!!!,本來此函數帶三個參數,我們這裏只需要傳兩個參數.
ADODataSet1.CommandText := '{call PKG_JCCTEST1.GetSubAndSum2(?,?)}' ;
//***C 順序有關,createparam必須放在commandtext賦值語句之後.
// 創建第一個參數,對應call中的第一個?,ftinteger爲類型,10爲長度,45爲傳入的實參值
ADODataSet1.Parameters.CreateParameter('p1',ftinteger,pdinput,10,45);
//創建第二個參數,根據createparameter的順序 自動與call中的第二個參數對應
ADODataSet1.Parameters.CreateParameter('p2',ftinteger,pdinput,10,4);
//下面調用ADODataSet1 的open方法,返回數據集(對應包過程的遊標)
ADODataSet1.Open ;
//根據存儲過程,數據集只有一條記錄,所以不需要用while do 來遍歷數據集,直接取數據了
//此處的字段名根據包過程中的返回遊標 對應的字段名來取
//定義的存儲過程返回遊標如: open ResultCursor for
// select p1-p2 as "sum", p1+p2 as "sub" from dual;
//把對應的字段值取出來即可
AResult := ADODataSet1.Fields.FieldByName('sub').Value ;
BResult := ADODataSet1.Fields.FieldByName('sum').Value ;
//顯示結果
showmessage(inttostr(AResult)) ;
showmessage(inttostr(BResult)) ;
end;
三.在delphi中利用AdoDataSet調用上述第二個存儲過程
還是利用上述的AdoDataSet1來調用第二個存儲過程,無需任何改動,加第二個按鈕,單擊時代碼如下:
procedure TForm1.Button2Click(Sender: TObject);
begin
ADODataSet1.Close ;
ADODataSet1.CommandType := cmdText ;
ADODataSet1.Parameters.Clear ;
//***利用call方法調用oracle過程時,參數必須由?來傳, 即使你要傳的參數爲常理
//輸出遊標的參數不需要指定!!!!!!,本來此函數帶兩個參數,我們這裏只需要傳一個參數.
ADODataSet1.CommandText := '{call PKG_JCCTEST1.GetClass2(?)}' ;
//***C 順序有關,createparam必須放在commandtext賦值語句之後.
// 創建第一個參數,對應call中的第一個?,ftinteger爲類型,10爲長度,20爲傳入的實參值
ADODataSet1.Parameters.CreateParameter('p1',ftinteger,pdinput,10,20);
//下面調用ADODataSet1 的open方法,返回數據集(對應包過程的遊標)
ADODataSet1.Open ;
while not ADODataSet1.Eof do
begin
showmessage('CID : '+string(ADODataSet1.FieldByName('CID').Value) +
'--CNAME :' + string(ADODataSet1.FieldByName('CNAME').Value) +
'--PNUMBER :' + string(ADODataSet1.FieldByName('PNUMBER').Value)
) ;
ADODataSet1.Next ;
end ;
end;
四 利用adoquery調用第三個過程,不返回數據集的
procedure TForm1.Button3Click(Sender: TObject);
begin
AdoQuery1.Close ;
AdoQuery1.Parameters.Clear ;
AdoQuery1.SQL.Clear ;
AdoQuery1.SQL.Add('{call PKG_JCCTEST1.GetSubAndSum2(?,?)}') ;
AdoQuery1.Parameters.CreateParameter('P1',ftstring,pdinput, 50,'c11') ;
AdoQuery1.Parameters.CreateParameter('P2',ftstring,pdinput, 50,'cn11') ;
AdoQuery1.Parameters.CreateParameter('P3',ftinteger,pdinput, 50,25) ;
AdoQuery1.ExecSQL ;
end;
五 利用adoquery調用第一個過程,返回數據集的.
procedure TForm1.Button4Click(Sender: TObject);
begin
AdoQuery1.Close ;
AdoQuery1.Parameters.Clear ;
AdoQuery1.SQL.Clear ;
AdoQuery1.SQL.Add('{call PKG_JCCTEST1.GetSubAndSum2(?,?)}') ;
AdoQuery1.Parameters.CreateParameter('P1',ftinteger,pdinput, 50,25) ;
AdoQuery1.Parameters.CreateParameter('P2',ftinteger,pdinput, 50,22) ;
AdoQuery1.Open ;
Showmessage(string( AdoQuery1.FieldByName('sub').Value)+'-'+
string( AdoQuery1.FieldByName('sum').Value));
end;
六.關於三層體系的此類問題
兩層的解決了,三層類似.
中間層用tadodataset 或tadoquery (+tdatasetprovider),中間層的adoconnection的連接字符串加上plsqlRset=1;
客戶端用clientdataset ,大同小異,舉例如下:
begin
//調用相應的過程
ClientDataSet1.Close ;
ClientDataSet1.Params.Clear ;
ClientDataSet1.CommandText := '{call PackageName.ProcedureName(?,?)}' ;
ClientDataSet1.Params.CreateParam(ftInteger , 'ParamName1', ptInput) ;
ClientDataSet1.Open ;
end ;
//法2
一、先在 Oracle 建好
CREATE OR REPLACE PACKAGE pkg_test
AS
TYPE myrctype IS REF CURSOR;
PROCEDURE get(i_test INTEGER,p_rc OUT myrctype);
END pkg_test;
CREATE OR REPLACE PACKAGE BODY pkg_test
AS
PROCEDURE get(i_test INTEGER,p_rc OUT myrctype) IS
BEGIN
IF i_test = 0 THEN
OPEN p_rc FOR SELECT SYSDATE FROM dual;
ELSE
OPEN p_rc FOR SELECT * FROM tab;
END IF;
END get;
END pkg_test;
二、用 Delphi 調用
建一個窗體,拖動控件 AdoConnection1 , ADOStoredProc1 和 Button1
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
i:=1;
try
with DM.ADOConnection1 do
begin
ConnectionString:=
'Provider=OraOLEDB.Oracle.1;'
+ 'Password=hyc;'
+ 'Persist Security Info=True;'
+ 'User ID=hyc;'
+ 'Data Source=orahyc;'
+ 'Extended Properties="PLSQLRSet=1;"';
Open;
end;
except
showMessage('連接不成功');
exit;
end;
try
with DM.ADOStoredProc1 do
begin
Connection := DM.ADOConnection1;
Parameters.Clear;
ProcedureName:= 'pkg_test.get';
Parameters.CreateParameter('p1',ftInteger,pdInput,10,1);
Open;
end;
except
showMessage('無法執行過程.');
end;
showMessage('成功獲取數據!');
while not DM.ADOStoredProc1.Eof do
begin
stringgrid1.Cells[0,i]:=inttostr(DM.ADOStoredProc1.FieldByName('pkid').AsInteger);
stringgrid1.Cells[1,i]:=DM.ADOStoredProc1.FieldByName('fld').AsString;
i:=i+1;
DM.ADOStoredProc1.Next;
end;
end;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.