1

第一关我对 Delphi 还有些陌生,所以这可能是一个被忽视的“平凡细节”。[提前抱歉]

我需要从包中包含的 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 分配参数值,但没有任何运气。如果它更容易或产生结果,我不会反对从函数返回 TDataSet。数据用于填充自定义对象属性。

4

2 回答 2

3

正如 paulsm4 中提到的this answer,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;
于 2012-10-25T01:55:24.423 回答
2

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

with strProc.Params.Add do
 begin
   Name := 'abbr';
   ParamType := ptInput;
   Value := ZZZTOP';
   ...
 end;
于 2012-10-25T00:22:47.973 回答