如何使用Delphi和DBExpress从存储过程中将Oracle Cursor作为客户端数据集返回

时间:2012-10-24 17:12:31

标签: delphi cursor oracle11g delphi-xe2 dbexpress

第一关我对德尔福仍然有点绿色,所以这可能是一个“平凡的细节”,正在被看过。 [提前抱歉]

我需要从包中包含的Oracle 11g游标创建TSQLDataset或TClientDataSet。我使用Delphi XE2和DBExpress连接到DB和DataSnap,将数据发送回客户端。

我在使用Delphi代码执行存储过程时遇到问题。

打包头

create or replace
PACKAGE KP_DATASNAPTEST AS 
  procedure GetFaxData(abbr varchar2, Res out SYS_REFCURSOR);
END KP_DATASNAPTEST; 

套餐正文

create or replace
PACKAGE  body KP_DATASNAPTEST AS 
  procedure GetFaxData(abbr varchar2, Res out SYS_REFCURSOR)is
  Begin
    open Res for 
      SELECT  Name, 
              Address1, 
              City, 
              fax_nbr 
      FROM    name 
      JOIN phone on name.Abrv = phone.abrv 
      WHERE phone.fax_nbr is not null and name.abrv = abbr;
  end;
END KP_DATASNAPTEST;

我在SQL Developer中执行此过程没有问题,问题出在DataSnap服务器上的此代码中:

function TKPSnapMethods.getCDS_Data2(): OleVariant;
var
  cds: TClientDataSet;      
  dsp: TDataSetProvider;
  strProc: TSQLStoredProc;      
begin
  strProc := TSQLStoredProc.Create(self);
  try
    strProc.MaxBlobSize := -1;
    strProc.SQLConnection:= SQLCon;//TSQLConnection

    dsp := TDataSetProvider.Create(self);
    try
      dsp.ResolveToDataSet := True;
      dsp.Exported := False;
      dsp.DataSet := strProc;
      cds := TClientDataSet.Create(self);
      try
        cds.DisableStringTrim := True;
        cds.ReadOnly := True;
        cds.SetProvider(dsp);

        strProc.Close;
        strProc.StoredProcName:= 'KP_DATASNAPTEST.GetFaxData';
        strProc.ParamCheck:= true;
        strProc.ParamByName('abbr').AsString:= 'ZZZTOP';
        strProc.Open; //<--Error: Parameter 'Abbr' not found. 

        cds.Open;
        Result := cds.Data;
      finally
        FreeAndNil(cds);
      end;
    finally
      FreeAndNil(dsp);
    end;
  finally
    FreeAndNil(strProc);
    self.SQLCon.Close;
  end;
end;

我也试过通过ClientDataSet分配param值而没有任何运气。 如果它更容易或产生结果,我不会被认为从函数返回TDataSet。数据用于填充自定义对象属性。

2 个答案:

答案 0 :(得分:3)

正如this answer中提到的paulsm4,Delphi并不关心获取存储过程参数描述符,因此您必须自己完成。要从包中获取Oracle存储过程的参数,您可以尝试使用GetProcedureParams方法使用参数描述符填充列表,并使用LoadParamListItems过程填充该列表Params集合。在代码中,它可能如下所示。

请注意,以下代码是根据文档在浏览器中编写的,因此未经测试。是的,关于释放ProcParams变量,这是由FreeProcParams过程完成的:

var
  ProcParams: TList;
  StoredProc: TSQLStoredProc;
  ...
begin
  ...
  StoredProc.PackageName := 'KP_DATASNAPTEST';
  StoredProc.StoredProcName := 'GetFaxData';
  ProcParams := TList.Create;
  try
    GetProcedureParams('GetFaxData', 'KP_DATASNAPTEST', ProcParams);
    LoadParamListItems(StoredProc.Params, ProcParams);
    StoredProc.ParamByName('abbr').AsString := 'ZZZTOP';
    StoredProc.Open;
  finally
    FreeProcParams(ProcParams);
  end;
  ...
end;

答案 1 :(得分:2)

我认为Delphi不会自动识别Oracle参数名称并为您填写。我想你需要添加参数。例如:

with strProc.Params.Add do
 begin
   Name := 'abbr';
   ParamType := ptInput;
   Value := ZZZTOP';
   ...
 end;