Как объединить данные из разных баз данных?

Я столкнулся с необходимостью объединения двух выборок из разных баз данных, а именно paradox (в bde) и сервера ms sql.

В настоящее время bde (через TQuery) используется только в этой части программы (т.е. dbgrid). Теперь мне нужно добавить некоторые данные, хранящиеся в базе данных сервера ms sql (с которой я обычно использую TADOQuery), в ту же сетку.

Хотя запросы выполняются по совершенно разным таблицам, результирующий набор столбцов именуется и типизируется одинаково (я имею в виду, что если бы у меня были эти таблицы, скажем, в базе данных сервера ms sql, я мог бы использовать для этого тривиальное объединение).

Есть ли способ объединить выбранные из них наборы записей в delphi7, чтобы я мог использовать результат в качестве источника данных для dbgrid?


person horgh    schedule 19.12.2012    source источник
comment
Я не знаю delphi, но в .net у нас есть списки, и вы можете добавить все записи одного типа в список, а затем преобразовать их в DataTable.   -  person Mahdi Tahsildari    schedule 19.12.2012
comment
BDE поддерживает (или поддерживает) гетерогенные запросы — см. docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/. IIRC Я использовал несколько более десяти лет назад для некоторых быстрых и грязных слияний данных.   -  person Gerry Coll    schedule 19.12.2012


Ответы (5)


Вы можете использовать набор клиентских данных, созданный определениями, например. набор данных вашего набора данных 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;

другой попыткой может быть создание связанного сервера для парадокса, я этого не пробовал...

http://www.experts-exchange.com/Microsoft/Development/MS-SQL-Server/SQL_Server_2008/Q_24067488.html

person bummi    schedule 19.12.2012
comment
Хотя у меня нет доступа к experts-exchange.com, в любом случае спасибо (т.е. +1) за идею со связанным сервером. Может быть, я когда-нибудь попробую. И принять - за TClientDataSet. Мне удалось выполнить свою задачу с ним. Большое спасибо - person horgh; 20.12.2012

Нет проблем с AnyDAC LocalSQL. Вы можете выполнять SQL с любым набором данных, а не только выбирать SQL, вставлять, обновлять, удалять SQL.

person Branko    schedule 19.12.2012
comment
К сожалению, я предпочитаю использовать встроенный функционал. Все равно спасибо. - person horgh; 20.12.2012

Вы можете использовать встроенную функцию TClientDataSet для объединения данных путем добавления данных из второго набора данных к данным первого.

Есть разные способы сделать это, мой предпочтительный, потому что простой код будет состоять в том, чтобы добавить два DataSetProviders и связать их с каждым из ваших наборов данных, например

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

Затем, чтобы открыть ваши наборы данных, вы можете просто сделать следующее:

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

Чтобы это работало, оба набора данных должны соответствовать номеру поля и типам данных. Поскольку ваши структуры похожи, вы можете работать с приведением типов в вашем SQL, если это не происходит автоматически.

person jachguate    schedule 19.12.2012
comment
+1 - это действительно упростило бы работу с TClientDataSet. Спасибо - person horgh; 20.12.2012

BDE поддерживает (или поддерживает) гетерогенные запросы Это позволяет запросам охватывать более одного набора данных, но с ограниченным синтаксисом SQL.

IIRC Я использовал несколько более десяти лет назад для некоторых быстрых и грязных слияний данных, но я не могу вспомнить подробности - я не прикасался к BDE годами.

person Gerry Coll    schedule 19.12.2012
comment
Очень рад за вас: я не прикасался к BDE много лет. Я с нетерпением жду времени, когда смогу сказать то же самое о себе))... - person horgh; 20.12.2012

Несколько лет назад (Delphi 7) я использовал TxQuery, но не знаю, находится ли он еще в разработке.

Я нашел эту ссылку

person ErvinS    schedule 19.12.2012