domingo, 26 de noviembre de 2017

Recorrer un DataSet y actualizar registros

Si queremos actualizar un campo de una fila o registro mientras recorremos el TDataSet por ejemplo mediante un while, obtendremos un error en tiempo de ejecución. Con un ejemplo será más sencillo:

WHILE NOT ZQuery1.EOF DO
begin
  ZQuery1.Edit;
  ZQuery1.FieldByName('alguncampo').AsInteger:=0;   
  ZQuery1.Post
  ZQuery1..Next;
end;


El código precendente nos dará el error y es correcto que lo haga, porque no situamos el puntero al comienzo del DataSet que sería con ZQuery1.First.

ZQuery1.First;
WHILE NOT ZQuery1.EOF DO
begin
  ZQuery1.Edit;
  ZQuery1.FieldByName('alguncampo').AsInteger:=0;   
  ZQuery1.Post
  ZQuery1..Next;
end;


Otra manera de resolver esto es mediante el uso de ExecuteDirect (y más rápido si se trata de un gran volumen), si tenemos un identificador único, mejor:

ZQuery1.First;
WHILE NOT ZQuery1.EOF DO
begin
  ZConnection1.ExecuteDirect('UPDATE tabla SET alguncampo=0 WHERE    identificaorunico='+ZQuery1.FieldByName('id').AsString'+' ;');
  ZQuery1..Next;
end;


Se recomienda hacer esto cuando no podamos hacerlo mediante una sentencia SQL UPDATE, ya que puede ser lento dependiendo del volumen de datos.

viernes, 24 de noviembre de 2017

Borrar registros de un dataset mediante While

El problema aquí es que pasa con el puntero cuando se elimina un registro y el next. Pues bien, cuando se elimina el registro, pasa al siguiente, por lo tanto hay que evitar el next cuando se borra.

While not (DMF.ZQReg.EOF ) do
begin 

  if algunacondicion then
    begin
      nEmple:=DMF.ZQReg.FieldByName('regemple').AsInteger;
      dFechaHora:=DMF.ZQReg.FieldByName('regfechahora').AsDateTime;
      DMF.ZQReg.Edit;
      DMF.ZQReg.Delete;
      Inc(nContador);
    end
  else
    begin
      nEmple:=DMF.ZQReg.FieldByName('regemple').AsInteger;
      dFechaHora:=DMF.ZQReg.FieldByName('regfechahora').AsDateTime;
      DMF.ZQReg.Next;
    end;
end; 


En este caso debo eliminar registros duplicados de lector biométrico, en algunacondicion evaluo si el registro es duplicado y tomo los datos antes de borrarlo, porque a veces los datos están hasta quintuplicados.
Como puede verse, el Next lo realizo solo si no se elimina el registro (fila).

Si el volumen de datos a procesar es grande, conviene utilizar una conexión sin autocommit y utilizar BEGIN y COMMIT tal como se explica aquí.