如何删除FireDAC数据集中与特定值匹配的所有记录?

时间:2016-03-01 16:20:10

标签: delphi firedac

我有一个通常的while not EOF do循环,用于删除内存表中的某些记录。删除最后一条记录并未按预期发出EOF信号。这是我的代码:

mtCt.First;  
while Not mtCt.Eof do  
begin  
  if mtCtAmt.Value = 0.0 then
    mtCt.Delete
  else
    mtCt.Next;  
end;

如何删除FireDAC数据集中与特定值匹配的所有记录?

3 个答案:

答案 0 :(得分:0)

您必须转到最后的数据。

mtCt.Last;  
while Not mtCt.Bof do  
begin  
  if mtCtAmt.Value = 0.0 then
    mtCt.Delete
  else
    mtCt.Prior;  
end;

答案 1 :(得分:0)

这是所有Delphi数据集的正常行为。

如果您的删除逻辑与示例一样简单,您可以简单地忽略它,无论如何,下一次迭代将不满足删除条件,发出Next和EOF。

如果逻辑很复杂而你需要避免不必要的迭代,你可以使用这样的技巧:

var
  PrevRecNo: Integer;
begin
  mtCt.First;  
  while Not mtCt.Eof do  
  begin  
    if mtCtAmt.Value = 0.0 then
    begin
      // save the current record number 
      PrevRecNo := mtCt.RecNo;

      // delete will normally not change current record number
      // unless you've deleted the last record, in this case
      // the current record will be one less than before
      mtCt.Delete;

      // so, if the saved record number and the current one are
      // different, you've delete the last record, just issue a
      // Next in order to hit EOF and exit the while loop
      if mtCt.RecNo <> PrevRecNo then
        mtCt.Next;
    end
    else
      mtCt.Next;  
  end;

答案 2 :(得分:0)

您无需以这种方式导航数据集即可访问内部存储,例如:

function GetFieldIndex(Dataset: TFDDataSet; const FieldName: string): Integer;
var
  I: Integer;
begin
  Result := -1;
  for I := 0 to Dataset.Table.Columns.Count-1 do
    if Dataset.Table.Columns[I].Name = FieldName then
    begin
      Result := I;
      Break;
    end;
end;

procedure DeleteFromDataset(Dataset: TFDDataSet; const FieldName: string;
  const FieldValue: Variant);
var
  Col, Row: Integer;
begin
  Col := GetFieldIndex(Dataset, FieldName);
  if Col <> -1 then
  begin
    Dataset.BeginBatch;
    try
      { delete all rows without navigating through dataset; this should
        affect also rows that were about to be inserted but changes were
        not yet applied }
      for Row := Dataset.Table.Rows.Count-1 downto 0 do
        if Dataset.Table.Rows[Row].GetData(Col) = FieldValue then
          Dataset.Table.Rows[Row].Delete;
      { resync dataset with the just modified internal storage }
      Dataset.Resync([]);
    finally
      Dataset.EndBatch;
    end;
  end;
end;

用法:

DeleteFromDataset(FDMemTable, 'MyField', 0.0);