Berechnete und summierte Felder (FireDAC)

Aus Appmethod Topics
Wechseln zu: Navigation, Suche

Nach oben zu Arbeiten mit Datenmengen (FireDAC)


FireDAC stellt einige Typen für berechnete Felder bereit.

Allgemeine Informationen

Berechnete Felder sind virtuelle Felder, deren Werte nicht aus der Datenbank abgerufen oder in der Datenbank gespeichert werden, sondern auf der Clientseite berechnet werden. FireDAC unterstützt berechnete Felder aller TField.FieldKind-Typen:

  • fkCalculated – ein einfaches berechnetes Feld. Der Wert wird in der Ereignisbehandlungsroutine TDataSet.OnCalcFields berechnet.
  • fkInternalCalc – ein erweitertes berechnetes Feld. Der Wert kann wie zu regulären Feldern zugewiesen werden und wird im Zwischenspeicher für die Datenmengendatensätze gespeichert. Der Wert wird in der Ereignisbehandlungsroutine TDataSet.OnCalcFields oder mit in TField.DefaultExpression angegebenen Ausdrücken berechnet.
  • fkLookup – ein Nachschlagefeld. Der Wert wird automatisch berechnet, indem ein Wert aus einer Nachschlagedatenmenge als Schlüsselwert in dieser Datenmenge bereitgestellt wird.
  • fkAggregate – ein Feld, in dem Aggregate berechnet werden. Der Wert wird anhand eines in TAggregateField.Expression angegebenen Ausdrucks berechnet, der die Aggregatfunktionen COUNT, SUM, MIN, MAX, AVG beinhalten kann.

Zum Filtern, Sortieren und Suchen können nur die Felder fkInternalCalc und fkAggregate verwendet werden. Außerdem werden diese Felder mit anderen Datenmengenfeldern in persistente Streams oder Dateien gespeichert. Die Werte von berechneten Feldern können nicht im automatischen Modus in eine Datenbank eingetragen werden.

TFDTable unterstützt im Modus "Live-Datenfenster" keine aggregierten Felder.

Berechnete Standardfelder

Die Werte der berechneten Felder fkCalculated und fkInternalCalc können durch die Ereignisbehandlungsroutine TDataSet.OnCalcFields zugewiesen werden. Ein berechnetes Feld kann zu folgenden Zeitpunkten definiert werden:

  • Beim Entwurf mit dem Menüeintrag Felder-Editor... für Datenmengen.
  • Zur Laufzeit im Code. Verwenden Sie den folgenden Code, um beispielsweise ein berechnetes Feld zu erstellen, das Namen in Großbuchstaben enthält:
procedure TForm1.Form1CalcFields(ADataSet: TDataSet);
begin
  ADataSet.FieldByName('UName').AsString := UpperCase(ADataSet.FieldByName('Name').AsString);
end;

var
  oField: TField;
  i: Integer;
...
FDQuery1.FieldDefs.Updated := False;
FDQuery1.FieldDefs.Update;
for i := 0 to ADQuery1.FieldDefs.Count - 1 do
  FDQuery1.FieldDefs[i].CreateField(Self);

oField := TStringField.Create(FDQuery1);
oField.Size := 50;
oField.FieldName := 'UName';
oField.FieldKind := fkInternalCalc; // or fkCalculated
oField.DataSet := FDQuery1;

FDQuery1.OnCalcFields := Form1CalcFields;
FDQuery1.Open;

Mit Ausdrücken berechnete Felder

Das Feld fiInternalCalc kann automatisch durch einen in TField.DefaultExpression angegebenen Ausdruck berechnet werden. Die Ereignisbehandlungsroutine TDataSet.OnCalcFields und eine explizite Wertzuweisung sind nicht erforderlich. Der Ausdruck kann nicht geändert werden, wenn die Datenmenge aktiv ist. Zum Beispiel:

var
  oField: TField;
  i: Integer;
...
FDQuery1.FieldDefs.Updated := False;
FDQuery1.FieldDefs.Update;
for i := 0 to FDQuery1.FieldDefs.Count - 1 do
  FDQuery1.FieldDefs[i].CreateField(Self);

oField := TStringField.Create(FDQuery1);
oField.Size := 50;
oField.FieldName := 'UName';
oField.FieldKind := fkInternalCalc;
oField.DefaultExpression := 'UPPER(Name)';
oField.DataSet := FDQuery1;

FDQuery1.Open;

Aggregierte Felder

Die Verwaltung von aggregierten fkAggregate-Feldern entspricht der Verwaltung von mit Ausdrücken berechneten Feldern. FireDAC berechnet aggregierte Felder, wenn TFDDataSet.AggregatesActive auf True gesetzt ist (standardmäßig ist dieser Wert auf False gesetzt). Der aggregierte Ausdruck kann nicht geändert werden, wenn die Datenmenge aktiv ist. Gehen Sie beispielsweise folgendermaßen vor, um ein aggregiertes Feld zu erstellen:

var
  oField: TAggregateField;
  i: Integer;
...
FDQuery1.FieldDefs.Updated := False;
FDQuery1.FieldDefs.Update;
for i := 0 to FDQuery1.FieldDefs.Count - 1 do
  FDQuery1.FieldDefs[i].CreateField(Self);

oField := TAggregateField.Create(FDQuery1);
oField.FieldName := 'Total';
oField.Expression := 'SUM((ItemPrice + ItemTaxes) * ItemCount)';
oField.DataSet := FDQuery1;

FDQuery1.AggregatesActive := True;
FDQuery1.Open;

Für ein aggregiertes Feld kann eine Gruppierung definiert werden. Der Wert wird dann für die Datensätze mit denselben Indexfeldwerten anstatt für alle Datensätze berechnet. Führen Sie die folgenden Schritte aus, um die Gruppierung zu definieren:

  • Setzen Sie TAggregateField.IndexName auf den Namen des Index, der für die Gruppierung verwendet werden soll. Standardmäßig wird der aktuelle Index verwendet.
  • Setzen Sie TAggregateField.GroupingLevel auf die Anzahl der indizierten Felder, die für die Gruppierung verwendet werden sollen. Standardmäßig ist der Wert auf 0 gesetzt (keine Felder und keine Gruppierung).

Ein aggregiertes Feld gibt immer null zurück, wenn sich eine Datenmenge im Status dsInsert befindet.

Aggregierte Werte

Die FireDAC-Anwendung kann auch mit der Sammlung TFDDataSet.Aggregates aggregierte Werte definieren. TFDDataSet.Aggregates ist weniger schwerfällig als Felder und kann jederzeit, auch wenn die Datenmenge aktiv ist, definiert werden. Zum Beispiel:

with FDQuery1.Aggregates.Add do begin
  Name := 'Total';
  Expression := 'SUM((ItemPrice + ItemTaxes) * ItemCount)';
  Active := True;
end;
FDQuery1.AggregatesActive := True;
...
Label1.Caption := VarToStr(FDQuery1.Aggregates[0].Value);

Siehe auch