如何在Delphi中調用oracle的存儲過程返回數據集

如何在Delphi中調用oracle的存儲過程返回數據集

【delphi+oracle報表解決方案(一)】delphi中調用oracle的存儲過程(分帶返回遊標,不返回值兩種)
關鍵字: delphi ,oracle存儲過程,遊標,返回數據集,報表

注:delphi 6+ oracle 8.1.6

一.創建包與包體

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 ;


=============================================================================================

一、 TADOStoredProc 類方法,動態參數創建:

1、CreateParameter方法; // 慣用此招

var

StProc: TADOStoredProc;

iPara1: byte;

iPara2: byte;

begin

StProc := TADOStoredProc.Create(nil);

StProc.Close;

StProc.Connection := con; // TADOConnection

StProc.ProcedureName := SP_NAME; // StoredProc Name

with StProc.Parameters do

begin

Clear;

CreateParameter('@para1', ftInteger, pdInput, 1, ipara1);

CreateParameter('@para2', ftInteger, pdOutput, 1, Null);

end;

StProc.prepared;

try

StProc.ExecProc;

//StProc.open; // 返回數據集

finally

StProc.free; // 如使用數據感知控件,慎用free,數據從何而來

end;

end;

2、AddParameter方法

// 省去變量聲明、創建、執行過程,同上

with StProc.Parameters.AddParameter do

begin

Name := '@para1';

DataType := ftInteger;

Direction := pdInput;

value := iPara1;

end;

with StProc.Parameters.AddParameter do

begin

Name := '@para';

DataType := ftWideString;

Direction := pdOutput;

end;

二、關於靜態參數刷新

StProc.ProcedureName:='getid';

StProc.Parameters.Refresh;

// 切記,刷新後賦值,下爲Delphi help 幫助原文。

// (個人意見)參數就已分配內存,故賦值在後

// to ensure a parameter collection has the most up to date information on

// available parameters.

StProc.Parameters.ParamByName('@para1').value := iPara1;

--------------------------------------------------

問:你好:
看到你的關於DELPHI調用ORACLE存儲過程返回結果集的文章,很受觸發。
我已經實現了在DELPHI裏調用ORACLE存儲過程,通過一個遊標參數,返回一個結果集的情況。現在有個問題:在存儲過程裏,可以實現多個弱遊標參數輸出多個結果集,但是,在DELPHI裏,我不知道,怎麼取得這第二個或其後的通過遊標返回的結果集。通過ADO只能取得第一個結果集。

如果你知道解決方案,請EMAIL聯繫我。
不勝感激。

答:

用nextrecordset方法就可以了,代碼如下:
var
vTemp1:integer;
begin
....
ADODataSet1.Open;
ADODataSet2.Recordset:=ADODataSet1.NextRecordset(vTemp1);
showmessage(ADODataSet2.FieldValues['CID']);
end;

問:怎麼連接局域網內的oracle的數據呢?
連接字符串應該怎麼寫呢?
Provider=OraOLEDB.Oracle.1;Password=KXD;Persist Security Info=True;User ID=KXD;Data Source=TEST3;PLSQLRSet=1
我用的adoquery控件。

答:以下三個參數根據你的情況修改就可以了
Data Source=TNS名稱
User ID=用戶名
Password=密碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章