Alle Strings einer Spalte zusammenfassen

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Alle Strings einer Spalte zusammenfassen

Beitrag von Aliobaba »

Hallo,

Ich möchte gerne zwischen zwei Programmstarts feststellen, ob sich am Inhalt einer Datenbank-Spalte etwas geändert hat.
Alle Spalteninhalte werden in einen String geschrieben (hier: "mmm") und von diesem String dann ein MD5-Hash gebildet und dieser dann gespeichert und verglichen mit vorangegangen gleichen Aktionen.
Bisher habe ich das immer so gemacht, dass ich Zeile für Zeile der Datenbank durchgegangen bin und die entsprechenden Spalteninhalte in einen String geschrieben habe.
Nun habe ich den SQL-Befehl
"SELECT GROUP_CONCAT(CTitelB, ", " ) FROM MyPL) Where PLId = '+ sss "
entdeckt, der diese Aufgabe recht elegant übernimmt.

Allerdings muss ich das Ergebnis der "Select"-Abfrage erst in eine andere DB-Spalte per "update" eintragen, um an das Ergebnis dieser Select-Abfrage zu kommen.

Gibt es eine Möglichkeit, den Inhalt dieser oben aufgeführten Select-Abfrage direkt in eine String-Variable zu übertragen?

Schönen Sonntag!
Aliobaba

Code: Alles auswählen

procedure TF_TSV.Button1Click(Sender: TObject);
var
  sss , mmm : string;
begin
   Ffufe.DB_Alle_zeigen_Sort_Titel_Fundus_2_Liste;
   if Ffufe.ZQueryFundus2.RecordCount = 0 then exit;
   Ffufe.ZQueryFundus2.First;
   sss := Ffufe.ZQueryFundus2.FieldByName('PLId').AsString;
   Form_Start.ZConneu.ExecuteDirect( 'UPDATE MyPL SET Cyyy2 = (SELECT GROUP_CONCAT(CTitelB, ", " ) FROM MyPL) Where PLId = '+ sss ) ;
   Ffufe.ZQueryFundus2.Refresh;
   mmm := Ffufe.ZQueryFundus2.FieldByName('Cyyy2').AsString ;
   Showmessage(mmm);
end;
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: Alle Strings einer Spalte zusammenfassen

Beitrag von Aliobaba »

Ach ja:
Datenbank ist "SQLite" unter "ZEOS"
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

Sieben
Beiträge: 202
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: Alle Strings einer Spalte zusammenfassen

Beitrag von Sieben »

Da das ja auch nur ein SELECT ist, kannst du es natürlich auch mit Open abfragen und zB mit

Code: Alles auswählen

MyQuery.Fields[0].AsString
auslesen. Wenn du lieber einen eigenen Feldnamen statt des Ausdrucks möchtest, musst du den unmittelbar nach dem Ausdruck angeben:

Code: Alles auswählen

SELECT GROUP_CONCAT(CTitelB, ", " ) MySum FROM MyPL 
und bekommst den gewünschten String dann mit

Code: Alles auswählen

MyQuery.FieldByName('MySum').AsString
Es spricht aber nichts gegen die erste Variante - du weißt ja, dass das Ergebnis immer nur die eine Spalte hat.

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: Alle Strings einer Spalte zusammenfassen

Beitrag von Aliobaba »

Wahrscheinlich habe ich mich unglücklich ausgedrückt:
Das Ergebnis der Select-Abfrage muss ich dabei ja zwingend in ein von mir gewähltes und bereits vorhandenes Feld der Datenbank eintragen.
Mich würde interessieren, ob ich an dieses Ergebnis auch "direkt" heran komme, also OHNE Eintrag in ein Datenbank-Feld.
Wenn ich zum Beispiel in einem SQL-Editor diesen Select-Befehl eingebe, dann erhalte ich das Ergebnis angezeigt OHNE dass ich dafür ein eigenes Feld in der Datenbank bereit halten muss.

Ich stelle mir das in etwa so vor:

Ergebnis-String := Meine_Datenbank.ExecuteDirect( 'SELECT GROUP_CONCAT( CPfadG ) FROM MyPL' ) ;
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Alle Strings einer Spalte zusammenfassen

Beitrag von af0815 »

Aliobaba hat geschrieben:
So 13. Mär 2022, 17:55
Wenn ich zum Beispiel in einem SQL-Editor diesen Select-Befehl eingebe, dann erhalte ich das Ergebnis angezeigt OHNE dass ich dafür ein eigenes Feld in der Datenbank bereit halten muss.
Was hindert dich daran, das in eine Query zu schreiben und mit open zu aktivieren. Wenn du ein Dataset erwartest, dann nimm kein Execute, sondern Open und den Rest im Code.
Ein Sql Editor zeigt dir normalerweise Datensets an.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Sieben
Beiträge: 202
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: Alle Strings einer Spalte zusammenfassen

Beitrag von Sieben »

Nichts anderes meinte ich auch. Nimm einfach eine Query, übergib ihr das SELECT-Statement, öffne sie mit Open und lies das Feld aus. Genau so, wie du aktuell dein Dummy-Feld abfragst. Die Ergebnismenge ist in diesem Falle immer eine Tabelle mit einer Spalte und einer Reihe, genau wie sie dir auch im SQL-Editor angezeigt wird.

Nur mal so als Pseudo-Beispiel, musst du ggf anpassen, weil ich Zeos nicht kenne:

Code: Alles auswählen

function TMyForm.GetConcatString: string
begin
  Result := EmptyStr;
  with TZQuery.Create(nil) do
  try
    DataBase := MyDatabase;
    SQL.Add('SELECT GROUP_CONCAT(CTitelB, ", " ) FROM MyPL');
    Open;
    Result := Fields[0].AsString;
    Close;
  finally
    Free;
  end;
end;

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: Alle Strings einer Spalte zusammenfassen

Beitrag von Aliobaba »

Hallo,
ich denke, ich muss dies aufgeben: Ich krieg's nicht hin.

Code: Alles auswählen

 function TF_TSV.GetConcatString: string ;
  begin
   With Ffufe.ZQueryFundus2 do
   Begin
      SQL.Clear;
      SQL.Add('SELECT GROUP_CONCAT(CTitelB, ", " ) MySum FROM MyPL');  // funktioniert nicht; auch ohne "MySum"
     // SQL.Add('SELECT * FROM MyPL WHERE CKue is not Cxxx3 ');  // Mit dieser Zeile funktioniert die Abfrage im restlichen Programm
      Open;
   end;
   //Result := Ffufe.ZQueryFundus2.Fields[0].AsString;  // habe es auch ohne "MySum" probiert.
   Result := Ffufe.ZQueryFundus2.FieldByName('MySum').AsString;
  end;   
Damit habe ich es probiert (in allen möglichen Variationen :( )
Es kommt die Fehlermeldung "Field not found" (Das Feld "PLId") , obwohl alle Felder (auch "PLId") der Datenbank in der Query "gemeldet" sind und obwohl ich dieses Feld ja hier gar nicht brauche/anspreche.

Und hier erscheint bei "DataBase": Identifier not found "Database"

Code: Alles auswählen

function TF_TSV.GetConcatString: string ;
begin
  Result := EmptyStr;
  with TZQuery.Create(nil) do
  try
    DataBase := 'MyPL';
//    ZQuery.DataBase := 'MyPL';
    SQL.Add('SELECT GROUP_CONCAT(CTitelB, ", " ) FROM MyPL');
    Open;
    Result := Fields[0].AsString;
    Close;
  finally
    Free;
  end;
end;       
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

Sieben
Beiträge: 202
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: Alle Strings einer Spalte zusammenfassen

Beitrag von Sieben »

Was heißt an dieser Stelle 'funktioniert nicht':

Code: Alles auswählen

      SQL.Add('SELECT GROUP_CONCAT(CTitelB, ", " ) MySum FROM MyPL');  // funktioniert nicht; auch ohne "MySum"
Gibt es beim Open eine Fehlermeldung und wenn ja, welche?
Allobaba hat geschrieben:Und hier erscheint bei "DataBase": Identifier not found "Database"
Wie gesagt kenne ich die Zeos-Komponenten nicht. Kann sein, dass das entsprechende Property zB Connection heißt. Sollte aber klar sein, dass es um das Dingens geht, das die Verbindung zur Datenbank herstellt. Das weist man dann aber auch nicht mit einem String-Literal zu, sondern nur mit dem Namen ohne Quotes:

Code: Alles auswählen

  ZQuery.Connection := MyPL;

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: Alle Strings einer Spalte zusammenfassen

Beitrag von Aliobaba »

Hallo und Guten Morgen,

vielen Dank für Eure Mühen; aber ich fürchte, dieser Umgang mit Datenbanken ist in diesem Punkt für meine Kenntnisse ganz einfach eine Nummer zu groß. Es fällt mir nicht ganz leicht, hier aufzugeben, aber ich möchte Euch nicht weiter mit meinen Fragen belästigen. Es wäre so als wenn man einem 4-Klässler die Integralrechnung erklären möchte.

Also vielen Dank!!
Aliobaba

<<<<<<<<<<<<<

So habe ich es nochmal probiert: Ging auch nicht :(

Code: Alles auswählen

function TF_TSV.GetConcatString: string ;
begin
  Result := EmptyStr;
//  with TZQuery.Create(nil) do
  with Ffufe.ZQueryFundus2 do
  try
    //DataBase := 'MyPL';
    Ffufe.ZQueryFundus2.Connection := Form_Start.ZConneu;
//    ZQuery.DataBase := 'MyPL';
    SQL.Add('SELECT GROUP_CONCAT(CTitelB, ", " ) FROM MyPL');
    Open;
    Result := Fields[0].AsString;
    Close;
  finally
    Free;
  end;
end;        
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: Alle Strings einer Spalte zusammenfassen

Beitrag von Aliobaba »

...man darf nie aufgeben!!

Es funktioniert:

Code: Alles auswählen

 Ffufe.ZQueryFundusxx.SQL.Text := 'SELECT GROUP_CONCAT(CTitelB, ", " ) FROM MyPL';
 Ffufe.ZQueryFundusxx.Open;
 Showmessage (Ffufe.ZQueryFundusxx.Fields[0].AsString);

 Ffufe.ZQueryFundusxx.SQL.Text := 'SELECT GROUP_CONCAT(CPfadG, ", " ) FROM MyPL';
 Ffufe.ZQueryFundusxx.Open;
 Showmessage (Ffufe.ZQueryFundusxx.Fields[0].AsString);
Ich habe eine völlig neue Query auf der Programmieroberfläche erstellt und die Angaben für "Felder bearbeiten" leer gelassen.
:) :)
Danke!!
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Alle Strings einer Spalte zusammenfassen

Beitrag von af0815 »

Aliobaba hat geschrieben:
Mo 14. Mär 2022, 08:22
So habe ich es nochmal probiert: Ging auch nicht :(
Das ist keine Aussage.

Ohne Beispielcode kann man nur herumstochern.

a ) geht das SQL Statement sicher in einem SQL-Editor ?
b ) Was liefert der genau zurück. Einen Wert, mehre Werte als Liste (Dataset)

Übrigends liegt im Lazarus-Verzeichnis unter Tools der Lazarus Data Desktop. Den kompilier dir mal und starte den und gib dort dein SQL-Statement ein. Was kommt dort heraus ?!

Weil es gibt viel Möglichkeiten das etwas "Ging auch nicht" ist.

1 ) Das SQL-Statement hat einen Fehler
2 ) Das SQL-Statement hat einen Logik-Fehler (oder Parameter falsch)
3 ) Es kommen keine Daten zurück (Query.EOF und Query.BOF sing zugleich aktiv)
4 ) Es kommt ein unerwartetes Ergebnis zurück (was kommt wirklich zurück -> Lazarus Data Desktop)

So, was ist es jetzt bei dir ?

Edit: Hat sich erledigt. Probier aber trotzdem den Lazarus Data Desktop mal aus. Da gibt es auch Menüpunkte wo man sich Quelltext erzeugen lassen kann :-) Hilft manchmal.

BTW: Vor einem ändern des SQL Textes in einer Query IMMER den Query.close machen, gefolgt von einem Query.clear , das stellt sicher das es sicher funktioniert.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: Alle Strings einer Spalte zusammenfassen

Beitrag von Aliobaba »

:)
Mach ich!
Aber jetzt erstmal Pause.
Wieder was gelernt; das ist gut so. Wenn auch bei recht flacher Lernkurve;
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

charlytango
Beiträge: 843
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: Alle Strings einer Spalte zusammenfassen

Beitrag von charlytango »

Aliobaba hat geschrieben:
So 13. Mär 2022, 09:49
Ich möchte gerne zwischen zwei Programmstarts feststellen, ob sich am Inhalt einer Datenbank-Spalte etwas geändert hat.
Alle Spalteninhalte werden in einen String geschrieben (hier: "mmm") und von diesem String dann ein MD5-Hash gebildet und dieser dann gespeichert und verglichen mit vorangegangen gleichen Aktionen.
Bisher habe ich das immer so gemacht, dass ich Zeile für Zeile der Datenbank durchgegangen bin und die entsprechenden Spalteninhalte in einen String geschrieben habe.
Ich habe bei diesem Thread irgendwie das Problem dass ich nicht verstehe warum du das so lösen willst.
Ist das nicht ein klassisches Historisierungsproblem?

Wollte ich Inhalte von Datenbankfeldern oder ganzen Spalten vergleichen würde ich das doch auch gleich in der Datenbank tun. Dazu hab ich sie ja. Größenproblem sollte das auch keines sein, denn den Vergleichswert eines zusammengesetzten Strings musst du ja auch irgendwo speichern. Außer du speicherst nur den MD5-Hash.

Variante A:
Einen zusammengesetzten String (aus anderen Tabellenspalten der gleichen Zeile) in eine Tabellenspalte zu schreiben würde ich mittels eines Update-Triggers direkt in der Datenbank erledigen. So etwas macht die Datenbank verlässlich, da kann man die DB auch eine gewisse Logik übernehmen lassen.

Variante B
Eine zweite (weitgehend baugleiche) Tabelle mit anderem Namen (zB- HIST_Altername) übernimmt das Speichern der Tabellenspalten die du vergleichen willst. Das aktualisieren der Tabellenspalten würde ich auch mittels Trigger lösen.
Dann brauchst du dich im Anwendungsprogramm gar nicht explizit drum kümmern. Lediglich die vergleichende Abfrage musst du noch ausführen - und da reicht eine die ein Count zurückgibt -- also nur zählt wo etwas verändert wurde.

Der Vorteil beider Varianten ist dass du auch sagen könntest welches Feld verändert wurde, falls das von Interesse ist

Hoffe ich bin nicht ganz am Thema vorbei ;)

Antworten