En muchas ocasiones uso tablas de memoria (sobre todo las
KbmMemTable) en conjunto con
SQLDirect para trabajar con datos en memoria y en algún momento grabar los cambios generados en la base de datos, esa parte es facil, ambos son TDataSet, pero ¿que ocurre si la tabla tiene miles de registros y realmente no hubo ningún cambio en los datos? Con un "changed" no es suficiente porque eso cambia cuando uno entra a editar un registro, aunque realmente no cambie nada.
Para eso hice un método, que por más que recorre todos los Fields de la tabla y podría parecer lento, siempre es más rápido que ejecutar updates en la base, sobre todo si la base de datos es remota.
En el uses hay que agregar
variants y
DB.
Código Delphi
[-]class function TFunciones.HayCambiosQueRegistrar(qryOrigen, qryDestino: TDataSet; Modificar: boolean): Boolean;
var
i: Integer;
NombreCampo: String;
rescmp: TVariantRelationship;
begin
Result := False;
for i := 0 to qryOrigen.FieldCount - 1 do
begin
NombreCampo := qryOrigen.Fields[i].FieldName;
if (qryDestino.FindField(NombreCampo) <> nil) then
begin
rescmp := VarCompareValue(qryOrigen[NombreCampo], qryDestino[NombreCampo]);
if (rescmp = vrNotEqual) or (not (rescmp = vrEqual)) then
begin
Result := True;
if not Modificar then
begin
Break;
end
else begin
if not (qryDestino.State in [dsEdit, dsInsert]) then
qryDestino.Edit;
qryDestino[NombreCampo] := qryOrigen[NombreCampo];
end;
end;
end;
end;
end;
Para usarlo lo que hago es recorrer los registros de la tabla orígen y buscar si existe el registro en el destino, si existe chequea si hay cambios, si hay alguno edita el destino. Si no existe agrega el registro.
Código Delphi
[-]
TablaDetalle.First;
while not TablaDetalle.EOF do
begin
if qryDetalle.Locate('ID', TablaDetalle.FieldByName('ID').AsInteger, []) then
begin
if TFunciones.HayCambiosQueRegistrar(TablaDetalle, qryDetalleRecepcion, False) then
begin
qryDetalle.Edit;
TFunciones.CopiarRegistroActual(TablaDetalle, qryDetalleRecepcion);
qryDetalle.Post;
end;
end
else
begin
qryDetalle.Append;
TFunciones.CopiarRegistroActual(TablaDetalle, qryDetalleRecepcion);
qryDetalle.Post;
end;
TablaDetalle.Next;
end;
ModuloDatos.GrabarEnTransaccion(qryDetalle);
En realidad, el código anterior no lo tengo igual, ya que el último parámetro realmente lo tengo en True, para que modifique la query si hay cambios, por lo que lo llamo así:
Código Delphi
[-]
if TFunciones.HayCambiosQueRegistrar(TablaDetalle, qryDetalleRecepcion, True) then
begin
qryDetalle.Post;
end;
Espero que les sirva, cualquier duda me pueden consultar...