如何将来自不同数据库的数据合并?

11

我需要将来自不同数据库的两个选择结果合并,分别是Paradox(在BDE中)和MS SQL Server。

目前程序仅在此部分(即dbgrid)中使用BDE(通过TQuery)。现在我需要将存储在MS SQL Server数据库中的一些数据(通常使用TADOQuery)添加到同一网格中。

虽然查询在完全不同的表上执行,但列的结果集命名和类型相似(我的意思是,如果我在MS SQL Server数据库中有这些表,我可以使用一个简单的联合操作进行操作)。

在Delphi7中,是否有任何方法将从这些数据库中选择的记录集合并,以便我可以将结果用作dbgrid的数据源?


我不了解Delphi,但在.NET中我们有List,您可以将所有相同类型的记录添加到List中,然后将其强制转换为DataTable。 - Mahdi Tahsildari
BDE支持(或曾支持)异构查询 - 请参阅http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devwin32/fhxr27506_xml.html。我记得十多年前我用过一些快速脏数据合并的方法。 - Gerry Coll
5个回答

5

您可以使用ClientDataSet,通过与您的SQL Server数据集定义进行比对并添加Paradox数据集的数据。在您的情况下,TFieldDefArray可以为空。

type
  TMyFieldDef = Record
    Name: String;
    Size: Integer;
    DataType: TFieldType;
  end;

  TFieldDefArray = array of TMyFieldDef;


function GetClientDSForDS(ADataSet: TDataSet; AFieldDefArray: TFieldDefArray; AClientDataSet: TClientDataSet = nil; WithRecords: Boolean = true)
  : TClientDataSet;
var
  i: Integer;
  Function NoAutoInc(ft: TFieldType): TFieldType;
  begin
    if ft = ftAutoInc then
      Result := ftInteger
    else
      Result := ft;
  end;

begin

  if Assigned(AClientDataSet) then
    Result := AClientDataSet
  else
    Result := TClientDataSet.Create(nil);
  Result.Close;
  Result.FieldDefs.Clear;

  for i := 0 to ADataSet.FieldCount - 1 do
  begin
    Result.FieldDefs.Add(ADataSet.Fields[i].FieldName, NoAutoInc(ADataSet.Fields[i].DataType), ADataSet.Fields[i].Size);
  end;

  for i := 0 to High(AFieldDefArray) do
    Result.FieldDefs.Add(AFieldDefArray[i].Name, AFieldDefArray[i].DataType, AFieldDefArray[i].Size);

  Result.CreateDataSet;
  for i := 0 to ADataSet.FieldCount - 1 do
  begin
    Result.FieldByName(ADataSet.Fields[i].FieldName).DisplayLabel := ADataSet.Fields[i].DisplayLabel;
    Result.FieldByName(ADataSet.Fields[i].FieldName).Visible := ADataSet.Fields[i].Visible;
  end;

  if WithRecords then
  begin
    ADataSet.First;
    while not ADataSet.Eof do
    begin
      Result.Append;
      for i := 0 to ADataSet.FieldCount - 1 do
      begin
        Result.FieldByName(ADataSet.Fields[i].FieldName).Assign(ADataSet.Fields[i]);
      end;
      Result.Post;
      ADataSet.Next;
    end;
  end;
end;

另一个尝试可能是为Paradox创建一个链接服务器,我没有尝试过... http://www.experts-exchange.com/Microsoft/Development/MS-SQL-Server/SQL_Server_2008/Q_24067488.html

虽然我无法访问_experts-exchange.com_,但还是感谢您提供的使用链接服务器的建议(+1)。也感谢您对TClientDataSet的推荐,我已经成功地完成了我的任务。非常感谢! - horgh

4

AnyDAC LocalSQL没有任何问题。您可以使用任何数据集执行SQL,不仅仅是select SQL,还包括insert、update和delete SQL。


不幸的是,我倾向于使用内置功能。尽管如此,谢谢。 - horgh

3
你可以使用内置的TClientDataSet功能,通过将第二个数据集的数据追加到第一个数据集的数据中来合并数据。
有不同的方法可以实现此操作,我推荐的是添加两个DataSetProviders,并将其链接到每个数据集,例如:
dspBDE.DataSet := MyTQuery;
dspADO.DataSet := MyAdoQuery;

然后,要打开你的数据集,你只需要执行以下操作:
MyClientDataSet.Data := dspBDE.Data;
MyClientDataSet.AppendData(dspADO.Data, True);

为使此操作生效,两个数据集必须匹配字段编号和数据类型。由于您的结构相似,如果这不会自动发生,则可以在SQL中进行类型转换。

+1 - 这将极大地简化使用 TClientDataSet 的工作。谢谢。 - horgh

2
BDE支持(或曾支持)异构查询,这允许跨越多个数据集的查询,但SQL语法有限。
我记得十年前我使用过一些快速脏数据合并的方法,但我无法记住具体细节 - 多年来我都没有接触BDE。

真为你感到高兴:“我已经多年没有接触BDE了。” 我正在等待那个时刻,迫不及待地想要对自己说同样的话))... - horgh

0
几年前(Delphi 7)我使用过TxQuery,但我不知道它是否仍在开发中。
我找到了这个链接

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接