2011-12-15 4 views
5

Estoy usando componentes de ZEOS para conectarme a una base de datos (antigua) de MDB.
Estoy haciendo una consulta que lee en muchos datos para enlazar a una base de datos diferente.En una consulta muy lenta, ¿cómo puedo indicar el porcentaje de progreso?

¿Hay alguna manera de indicar el progreso como un porcentaje?

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; 

¿Hay alguna manera para indicar el progreso de la consulta, o puede que sólo hacer esto si me separé las consultas individuales y eliminar los UNION 's.
Tarda aproximadamente 1 minuto en ejecutarse, lo que implica 8 uniones.

no veo cualquier acontecimiento que pueda utilizar para este propósito:

O debería fingir un OnCalcField en un campo en la consulta para hacer esto (si no está seguro de que va a trabajar incluso en principio).
¿O adjuntar una secuencia? no, da una operación no admitida en un Access DB

+0

Como ya he mencionado en un comentario más abajo, en base a la respuesta por user1031312, podría poner los datos en una cuadrícula cadena en lugar, a menos que usted depende de la funcionalidad del DBGrid. Si un TStringGrid está bien, puedo darte un buen ejemplo si es necesario dividir las consultas y combinar los resultados en la misma cuadrícula ... –

+0

@JerryDodge, solo necesito acceso de solo lectura, así que una cadena de caracteres me funcionaría. – Johan

+1

Sin conocer el recuento total de registros, será difícil mostrar una información 'x por ciento completada' – mjn

Respuesta

3

Digo dividir las consultas individuales y eliminar la unión, hacer un temporizador alrededor de cada consulta, dependiendo del promedio de tiempo tomado * el número de consultas restantes debe dar una estimación/actualizar un campo de texto para decir x de y consultas completadas (tiempo restante: -tiempo-)

+1

Sí, supongo que podría crear un componente de consulta por consulta y ejecutarlos uno después del otro. El problema es que me gustaría mostrar los datos en una grilla y eso es un poco difícil con todos los datos divididos. – Johan

+0

No creo que necesite un componente de consulta para cada uno, justo después de que haya terminado con una consulta, pase a la siguiente declaración en el mismo componente, pero todavía tiene un punto claro al adjuntar una fuente de datos para mostrar el datos ... –

+0

Si ese es el caso, ¿entonces posiblemente creando su propio conjunto de datos de cliente? Puede combinar resultados de múltiples consultas, o simplemente agregar sus propios datos a pedido, pero honestamente nunca he trabajado con ellos. Según los rumores de su situación, si decide dividir cada enunciado como se menciona en esta respuesta, entonces deberá combinar los datos de alguna manera en su propio conjunto de datos, y luego adjuntarlos a la fuente de datos (trabajando así en una cuadrícula). –

3

dividiría la gran consulta en consultas individuales; en el código, itera sobre el conjunto de resultados de cada consulta e inserta los valores manualmente en un conjunto de datos del cliente (cds). Los cds se pueden conectar a un dbgrid. Luego, puede mostrar cuándo se completa cada consulta: también puede mostrar el progreso después de manejar cada tupla, pero no sabrá cuántas tuplas hay en total, a menos que realice una consulta por separado que arroje un recuento de tuplas. El problema con el uso de tales cds no conectados es que debe definir los campos en el código. Aquí hay un ejemplo de algo similar que escribí anoche: todas las consultas actualizan un campo en los 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; 
Cuestiones relacionadas