Delphi中调用oracle的存储过程返回数据集

本文介绍如何使用Delphi通过ADO组件调用Oracle存储过程并处理返回的数据集。包括创建Oracle存储过程、使用ADODataset及ADOQuery进行调用的具体步骤及代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

选自csdn http://search.youkuaiyun.com/expert/topic/2280/2280860.xml?temp=2.169436e-02 论坛中jcc0128 网友的发言

 

{说明:以下代码均未测试,等测试后,再会删除本行说明.by chinmusam}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值