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

Posted

技术标签:

【中文标题】如何合并来自不同数据库的数据?【英文标题】:How to union data from different databases? 【发布时间】:2012-12-19 07:31:00 【问题描述】:

我遇到了合并来自不同数据库的两个选择的必要性,即 paradox (in bde) 和 ms sql server。

目前 bde(通过TQuery)仅用于程序的这一部分(即 dbgrid)。现在我需要将一些存储在 ms sql server 数据库(我通常使用TADOQuery)中的数据添加到同一个网格中。

虽然查询是在完全不同的表上执行的,但列的结果集的命名和类型相似(我的意思是,如果我有这些表,例如,在 ms sql server 数据库中,我可以为此使用一个普通的联合)。

有什么方法可以在 delphi7 中合并从这些中选择的记录集,以便我可以将结果用作 dbgrid 的数据源?

【问题讨论】:

我不知道 delphi 但在 .net 中我们有列表,您可以将所有相同类型的记录添加到列表中,然后将其转换为数据表。 BDE 支持(或支持)异构查询 - 请参阅 docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/…。 IIRC 我在十多年前使用了一些快速'n'dirty 数据合并。 【参考方案1】:

您可以使用由例如定义创建的客户端数据集。 SQL-Server 数据集的数据集并添加悖论数据集的数据。在您的情况下,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。我设法用它完成了我的任务。非常感谢【参考方案2】:

AnyDAC LocalSQL 没问题。您可以使用任何 DataSet 执行 SQL,不仅可以选择 SQL,还可以插入、更新、删除 SQL。

【讨论】:

不幸的是,我倾向于使用内置功能。不过,谢谢。【参考方案3】:

您可以使用内置 TClientDataSet 功能通过将第二个数据集中的数据追加到第一个数据集的数据来合并数据。

有不同的方法可以做到这一点,我更喜欢一种,因为简单的代码就是添加两个 DataSetProvider 并将其链接到您的每个 DataSet,例如

dspBDE.DataSet := MyTQuery;
dspADO.DataSet := MyAdoQuery;

然后,打开你的数据集,你可以这样做:

MyClientDataSet.Data := dspBDE.Data;
MyClientDataSet.AppendData(dspADO.Data, True);

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

【讨论】:

+1 - 这将真正简化TClientDataSet 的工作。谢谢【参考方案4】:

BDE 支持(或支持)heterogeneous queries 这允许查询跨越多个数据集,但 SQL 语法有限。

我在十多年前使用了一些 IIRC 来进行一些快速的'n'dirty 数据合并,但我不记得具体细节 - 我已经多年没有接触过 BDE。

【讨论】:

真为你高兴:“我已经很多年没有接触过 BDE”了。我正在等待我能够不耐烦地对自己说同样的话的时候))......【参考方案5】:

几年前(Delphi 7)我使用了 TxQuery,但我不知道它是否还在开发中

我找到了这个link

【讨论】:

以上是关于如何合并来自不同数据库的数据?的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB:将来自多个集合的数据合并为一个..如何?

合并来自不同粒度维度的数据

如何合并两个不同的数据帧,时间戳略有不同

Java - 合并来自不同数据源中的 2 个表的数据

来自不同数据源的产品表合并过程

如何在不合并索引的情况下连接具有不同多索引的两个数据帧?