数据库

本类阅读TOP10

·SQL语句导入导出大全
·SQL Server日期计算
·SQL语句导入导出大全
·SQL to Excel 的应用
·Oracle中password file的作用及说明
·MS SQLServer OLEDB分布式事务无法启动的一般解决方案
·sqlserver2000数据库置疑的解决方法
·一个比较实用的大数据量分页存储过程
·如何在正运行 SQL Server 7.0 的服务器之间传输登录和密码
·SQL中两台服务器间使用连接服务器

分类导航
VC语言Delphi
VB语言ASP
PerlJava
Script数据库
其他语言游戏开发
文件格式网站制作
软件工程.NET开发
如何在Delphi中调用oracle的存储过程返回数据集

作者:未知 来源:月光软件站 加入时间:2005-2-28 月光软件站

选自CSDN http://search.csdn.net/Expert/topic/2280/2280860.xml?temp=2.169436E-02 论坛中JCC0128 网友的发言

【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 ;


本人水平有限,如有不当与错误之处请指正!




相关文章

相关软件