在非常慢的查询中,如何指示进度百分比

发布于 2024-12-21 09:13:37 字数 1167 浏览 2 评论 0原文

我正在使用 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 DB 上提供不支持的操作

I'm using ZEOS components to connect to an (ancient) MDB database.
I'm doing a query that reads in lots of data to bridge into a different database.

Is there a way to indicate progress as a percentage?

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;

Is there a way to indicate progress of the query, or can I only do this if I split up the individual queries and eliminate the UNION's.
It takes about 1 minute to run, involving 8 unions.

I don't see any event that I can use for this purpose:

Or should I fake an OnCalcField on a field in the Query to do this (not sure if that will even work in principle).
Or attach a sequence? nope, gives unsupported operation on a Access DB

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

燃情 2024-12-28 09:13:37

我说拆分各个查询并消除联合,在每个查询周围设置一个计时器,具体取决于所用的平均时间 * 剩余查询的数量,您应该给出估计/更新文本字段以表示已完成的 y 个查询中的 x 个(时间剩余时间:-时间-)

I say split up the individual queries and eliminate the union, make a timer around each query, depending on the avg time taken * number of queries remaining you should give an estimate / update a text field to say x out of y queries completed (time remaining: -time-)

早乙女 2024-12-28 09:13:37

我会将庞大的查询拆分为单独的查询;在代码中,您迭代每个查询的结果集并将值手动插入到客户端数据集 (cds) 中。 CD 可以连接到 dbgrid。然后,您可以显示每个查询何时完成 - 您还可以在处理每个元组后显示进度,但您不会知道总共有多少个元组,除非您执行返回元组计数的单独查询。使用这种未连接的 CD 的问题是您必须在代码中定义字段。这是我昨晚写的一个类似的例子 - 查询全部更新 CD 中的一个字段。

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;

I would split the huge query into individual queries; in code, you iterate over each query's result set and manually insert the values into a clientdataset (cds). The cds can be connected to a dbgrid. Then you can show when each query completes - you could also show progress after each tuple is handled, but you won't know how many tuples in total there are, unless you perform a separate query which returns a count of tuples. The problem with using such an unconnected cds is that you have to define the fields in code. Here is an example of something similar which I wrote last night - the queries all update one field in the cds.

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文