На очень медленный запрос, как я могу указать процент прогресса - PullRequest
5 голосов
/ 16 декабря 2011

Я использую компоненты ZEOS для подключения к (древней) базе данных MDB.
Я делаю запрос, который читает много данных, чтобы соединиться с другой базой данных.

Есть ли способ указать прогресс в процентах?

procedure TForm13.ActionReadInMemoryExecute(Sender: TObject);
var
  QueryLine: string;
  FullQuery: string;
  Tablename: string;
  i: integer;
begin
  i:= 0;
  TableMeter.DisableControls;
  try
    TableMeter.First;
    FullQuery:= '';
    while not TableMeter.eof do begin
      Tablename:= TableMeter.FieldByName('tabelnaam').AsString;
      QueryLine:= ReplaceStr(ImportQuerySjabloon, cTabelname, Tablename);
      FullQuery:= FullQuery + QueryLine;
      if (TableMeter.RecNo < (TableMeter.RecordCount -1)) then begin
        FullQuery:= FullQuery + ' UNION ALL ';
      end;
      TableMeter.Next;
    end; {while}
    QueryImportMeterreadings.Close;
    QueryImportMeterreadings.SQL.Text:= FullQuery;
    QueryImportMeterreadings.Open;  <<-- takes a long time
  finally
    TableMeter.EnableControls;
  end;
end;

Есть ли способ указать ход выполнения запроса, или я могу сделать это, только если я разделю отдельные запросы и исключу UNION.
Бег занимает около 1 минуты, с участием 8 профсоюзов.

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

Или я должен подделать OnCalcField на поле в Запросе, чтобы сделать это (не уверен, будет ли это вообще работать).
Или приложить последовательность? Нет, дает неподдерживаемую операцию на БД Access

Ответы [ 2 ]

3 голосов
/ 18 декабря 2011

Я бы разбил огромный запрос на отдельные запросы;в коде вы перебираете набор результатов каждого запроса и вручную вставляете значения в набор данных клиента (cds).Диски могут быть подключены к dbgrid.Затем вы можете показать, когда завершается каждый запрос - вы также можете показать прогресс после обработки каждого кортежа, но вы не будете знать, сколько всего существует кортежей, если вы не выполните отдельный запрос, который возвращает количество кортежей.Проблема с использованием таких неподключенных компакт-дисков заключается в том, что вы должны определить поля в коде.Вот пример чего-то подобного, который я написал вчера вечером - все запросы обновляют одно поле в компакт-дисках.

const
 field1 = 'id';
 field2 = 'customer name';
 field3 = 'total debt';

procedure TTotalCustDebt.FormCreate(Sender: TObject);
var
 strings: tstrings;

begin
 with qTotalDebt do   // this is the clientdataset
  begin
   fielddefs.add (field1, ftInteger, 0, false);
   fielddefs.add (field2, ftString, 32, false);
   fielddefs.add (field3, ftInteger, 0, false);
   createdataset;
   fieldbyname (field1).visible:= false;
   open;
   addindex ('idx0', field2, [], '', '', 0);
   addindex ('idx1', field2, [ixDescending], '', '', 0);
   addindex ('idx2', field3, [], '', '', 0);
   addindex ('idx3', field3, [ixDescending], '', '', 0);
   strings:= tstringlist.create;
   getindexnames (strings);
   strings.free;
  end;
end;

procedure TTotalCustDebt.PopulateCDS;
begin
 dsTotalDebt.dataset:= nil;
 with qTotalDebt do
  begin
   emptydataset;
   indexfieldnames:= field1;  // initially sort by customer.id
  end;

 with qDBills do
  begin
   params[0].asdate:= dt;
   open;
   while not eof do
    begin
     qTotalDebt.append;
     qTotalDebt.fieldbyname (field1).asinteger:= qDBillsID.asinteger;
     qTotalDebt.fieldbyname (field2).asstring:= qDBillsName.asstring;
     qTotalDebt.fieldbyname (field3).asinteger:= qDBillsTot.asinteger;
     qTotalDebt.post;
     next
    end;
   close
  end;

  // show progress indicator

  with qDReceipts do
   begin
    params[0].asdate:= dt;
    open;
    while not eof do
     begin
      if qTotalDebt.findkey ([qDReceiptsID.asinteger]) then
       begin  // customer already exists
        qTotalDebt.edit;
        qTotalDebt.fieldbyname (field3).asinteger:= - qDReceiptsTot.asinteger
                                  + qTotalDebt.fieldbyname (field3).asinteger;
      end
     else
      begin  // add new record
       qTotalDebt.append;
       qTotalDebt.fieldbyname (field1).asinteger:= qDReceiptsID.asinteger;
       qTotalDebt.fieldbyname (field2).asstring:= qDReceiptsName.asstring;
       qTotalDebt.fieldbyname (field3).asinteger:= - qDReceiptsTot.asinteger;
      end;
     qTotalDebt.post;
     next
    end;
   close
  end;

 // show progress indicator
 // more queries
 // at end, attach the clientdataset to the TDataSource
 dsTotalDebt.dataset:= qTotalDebt;
end;
3 голосов
/ 16 декабря 2011

Я говорю, разделите отдельные запросы и устраните объединение, сделайте таймер вокруг каждого запроса, в зависимости от среднего времени выполнения * количества оставшихся запросов, вы должны дать оценку / обновить текстовое поле, чтобы сказать x из y запросов завершено (оставшееся время: -time -)

...