Fehler beim Löschen und Einfügen der Datensätze.

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
Luckner
Beiträge: 88
Registriert: Sa 18. Jan 2020, 09:56
OS, Lazarus, FPC: Winux (L 2.2.0 FPC 3.2.2)
CPU-Target: Windows 64-Bit

Fehler beim Löschen und Einfügen der Datensätze.

Beitrag von Luckner »

Hallo,
Habe folgende Routine:

Code: Alles auswählen

if ButtonStanze.Color = $00FF00 then
  begin
    DataModuleAbhaengikeiten.ZConnectionAbhaengikeiten.Connect;
    DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.Close;
    DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.SQL.Clear;
    DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.SQL.Add('SELECT * FROM ARTIKEL_STANZE WHERE ARTIKEL_NR = ' + QuotedStr(EditArtikelNr.Text));
    DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.Open;

    if not DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.IsEmpty then
    begin
      ShowMessage('Bin im Teil 1');
      DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.Close;
      DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.SQL.Clear;
      DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.SQL.Add('delete FROM ARTIKEL_STANZE WHERE ARTIKEL_NR = ' + QuotedStr(EditArtikelNr.Text));
      DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.ExecSQL;
      DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.Close;
      DataModuleAbhaengikeiten.ZConnectionAbhaengikeiten.Disconnect;
    end;

    if EditStanzeNr.Text <> '' then
    begin
      ShowMessage('Bin im Teil 2');
      DataModuleAbhaengikeiten.ZConnectionAbhaengikeiten.Connect;
      DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.Open;
      DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.Append;
      ShowMessage('Bin im Teil 3');
      DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_GridSTANZEN_NR.AsInteger:= StrToInt(EditStanzeNr.Text);
      DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_GridARTIKEL_NR.AsInteger:= StrToInt(EditArtikelNr.Text);

      DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.Post;
      ShowMessage('Bin im Teil 4');
      DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.Close;
      DataModuleAbhaengikeiten.ZConnectionAbhaengikeiten.Disconnect;
    end;
  end;                                                 
folgendes geschieht:
1) Wenn in dieser Tabelle kein Eintrag existiert, wird ein Datensatz eigefügt und Routine läuft über 'ShowMessage 2 bis 4 ohne Probleme.
2)Wenn in dieser Tabelle ein Eintrag existiert, wird dieser gelöscht (sehe ich direkt in der Tabelle) 'ShowMessage 1, 2 und Routine ergibt einen Fehler:
'Projekt Stanzen hat Exception-Klasse ausgelöst mit der Meldung: Can not open a Resultset'.
3) Da im Punkt 2) der Eintrag gelöscht wurde, ist ein nochmaliger Aufruf dieser Routine wieder ohne Fehler (wie beim Punkt 1).
Und so im Kreis. Woran liegt es, dass nach direktem Löschen eine Eintrages, kein Append funktioniert?

Gruß, Luckner

Benutzeravatar
six1
Beiträge: 788
Registriert: Do 1. Jul 2010, 19:01

Re: Fehler beim Löschen und Einfügen der Datensätze.

Beitrag von six1 »

Mir fallen sehr viele Kleinigkeiten an deinem Code auf, die ich definitiv anders lösen würde...

Das zentrale Problem ist aber wohl, dass du an der Query ein DBGrid hängen hast, was mit deinen ExecSql auf die Tabelle nicht zurecht kommt.

Möchtest du den Code in dieser ARt beibehalten, wäre die Lösung, vor ExecSql das Grid "abzuhängen" mit MyDBGrid.Datasource:=NIL; und nach Ausführung wieder die Datasource richtig einzustellen.

Du bekommst durch ExecSql kein gültiges Resultset für ein DBGrid zurück!
Gruß, Michael

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6216
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: Fehler beim Löschen und Einfügen der Datensätze.

Beitrag von af0815 »

Ich sehe das wie six1,

entweder man verwendet die Query und hängt dann das Grid ran, dann sollte man aber die Datensätze über die Funktionen vom Datenset bearbeiten. Wofürr glaubst du, sind die ganzen Funktionen im Datenset vorhanden und man kann in der Query angeben, was beim Einfügen, Löschen genau geschehen soll.

Faustregel, alles was Datensätze (Recordsets) - ist fast immer nur ein select datenfeld1 , datenfeld2 from MeineTabelle - zurück gibt dann an die visuellen DB Komponeneten gekoppelt werden. Alles andere soll nicht mit den visuellen DB Komponneten (wie bei dir DBGrid) verwendet werden.

Wenn es unbedingt so sein muss, so mache es mit einer alleinstehenden zweiten Query, die ja auch dynamisch erzeugt werden kann, anschliessend aber nicht vergessen die Daten aus dem Puffer in die DB zu bringen und dann in der Query die an das Grid gebunden ist, das Datenset neu vom Server zu laden. Weil sonst ist Chaos in der DB vorprogrammiert (Deine Punkte 2-3).
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Luckner
Beiträge: 88
Registriert: Sa 18. Jan 2020, 09:56
OS, Lazarus, FPC: Winux (L 2.2.0 FPC 3.2.2)
CPU-Target: Windows 64-Bit

Re: Fehler beim Löschen und Einfügen der Datensätze.

Beitrag von Luckner »

Habe jetzt ein weiteres Dataset eingesetzt, mit keinem DBGrid verbunden und bekomme den selben Fehler. Sobald ein 'delete' und ein 'append' huintereinander kommen ensteht ein Fehler.

Luckner

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6216
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: Fehler beim Löschen und Einfügen der Datensätze.

Beitrag von af0815 »

Luckner hat geschrieben:
Mo 17. Apr 2023, 18:16
Habe jetzt ein weiteres Dataset eingesetzt, mit keinem DBGrid verbunden und bekomme den selben Fehler. Sobald ein 'delete' und ein 'append' huintereinander kommen ensteht ein Fehler.
In SQL gibt es keine append, somit ist die Aussage schon mal komisch. Und was für ein Fehler wo ?!

Nochmals, diese einfachen Insert, Delete STatemnts macht man, wenn dann mit der Query alleine OHNE den SQL umzuladen. Die Query kann sich das mit dem Datenset selbst sehr gut ausmachen, wenn man die Query sauber mit Statements versorgt. Für das was du machst brauche ich keine 2te Query. Nur verwendet man dann halt Parameter statt dem String gefrickel mit dem QuotedStr und stellt ein ordentliches Selectstatemant zusammen. Dann kann die Query alleine abfragen, einfügen, löschen und bekommt die Informationen was sie machen soll aus dem Dataset und dem Zustand des Dataset.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Luckner
Beiträge: 88
Registriert: Sa 18. Jan 2020, 09:56
OS, Lazarus, FPC: Winux (L 2.2.0 FPC 3.2.2)
CPU-Target: Windows 64-Bit

Re: Fehler beim Löschen und Einfügen der Datensätze.

Beitrag von Luckner »

Hallo af0815,

warum gibt es in SQL kein append? In Delphi benutze ich es schon seid Jahren und ein Dataset bietet es auch an. Mag nicht 100% konform sein, wie ich es benutze aber es funktionierte bis zu dieser Routine. An einer anderen Stelle füge ich mit append mehrere Zeilen in einer Tabelle, ohne vorher etwas zu löschen, ohne Probleme. Habe in Delphi diese Routine ebenfalls erstellt und es funktioniert. Allerdings benutze ich dort nicht die Zeos-Komponenten. In der vorherigen Anwort von Dir (und von six1), würde es an der Verbindung zum DBGrid liegen, wenn es nicht funktioniert, deshalb ein weiteres Dataset ohne diese Verbindung. Aber daran liegt es nicht. In Delphi benutze ich auch nur ein Dataset. Weil man mir vor geraumer Zeit erläutet hat, dass Lazarus und Delphi ähnlich seien aber nicht identisch, dachte ich erst, dass man es in Lazarus in diesem Fall anders vorgehen muß.

Gruß, Luckner

Benutzeravatar
six1
Beiträge: 788
Registriert: Do 1. Jul 2010, 19:01

Re: Fehler beim Löschen und Einfügen der Datensätze.

Beitrag von six1 »

Du kannst x Dataset an eine Query hängen... was es nicht besser macht!
Das Resultset eines ExecSql von der Query stimmt nicht für die Datasource!

Nimm eine extra Query und erledige die Tabellenoperationen und nachher machst du bei der Query, wo das Dataset und Grid dranhängt ein enabled:=false/true
Gruß, Michael

Luckner
Beiträge: 88
Registriert: Sa 18. Jan 2020, 09:56
OS, Lazarus, FPC: Winux (L 2.2.0 FPC 3.2.2)
CPU-Target: Windows 64-Bit

Re: Fehler beim Löschen und Einfügen der Datensätze.

Beitrag von Luckner »

Hallo six1,

habe den Fehler gefunden. Nach dem

Code: Alles auswählen

     DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.Close;
      DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.SQL.Clear;
      DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.SQL.Add('delete FROM ARTIKEL_STANZE WHERE ARTIKEL_NR = ' + QuotedStr(EditArtikelNr.Text));
      DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.ExecSQL;
      DataModuleAbhaengikeiten.ZQueryEtiketten_Stanze_Grid.Close;
      DataModuleAbhaengikeiten.ZConnectionAbhaengikeiten.Disconnect;
und vor dem Append, habe ich ein 'select * FROM ARTIKEL_STANZE' gemacht und dann das ZQueryEtiketten_Stanze_Grid.Open. Und jetzt funktioniert es. Ein nur 'ZQueryEtiketten_Stanze_Grid.Open' geht nicht.
Ich dachte mir, dass wenn man Zquery.open macht, dann werden der SQL-Eintrag der Eigenschaft des Querys automatisch ausgeführt. In diesem Fall wohl nicht.

In Delphi benutze ich die Standart TDataset und dort scheint es anders zu sein.

Danke für Deine Gedanken und Gruß,
Luckner

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6216
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: Fehler beim Löschen und Einfügen der Datensätze.

Beitrag von af0815 »

Luckner hat geschrieben:
Di 18. Apr 2023, 12:05
warum gibt es in SQL kein append? In Delphi benutze ich es schon seid Jahren und ein Dataset bietet es auch an.
Halte einmal die Begriffe auseinander
SQL=DML: Select, Insert, Delete und Update
DataSetState: dsInactive, dsBrowse, dsEdit, dsInsert, dsSetKey, dsCalcFields, dsFilter, dsNewValue, dsOldValue, dsCurValue, dsBlockRead, dsInternalCalc, dsOpening, dsRefreshFields

Die Query kann alle Zustände die das Dataset haben kann verarbeiten OHNE extra Befehle. Die werden aufgrund des Wechsel des Zustandes des Dataset States von selbst in die entsprechenden SQL Befehle (DML) umgesetzt und das Dataset selbst damit auch synchron zu den Änderungen gehalten.

Das Datenset im nach einem öffen selbst im Zustand dsBrowse. Du kannst dem Datenset sagen, das du etwas anfügen willst -> Funktion Append, damit wird das Datenset in den Zustand dsInsert gebracht und ein neuer Datensatz angehängt. Wenn du jetzt du dem Dataset sags, es passt = Post so wird vom Dataset die Änderung in der Query angestossen. Die Query sieht das ein Datensatz angefügt wird und verwendet das was unter dem InsertSQL gespeichert ist. Anschließend geht das Dataset wieder in den State stBrowse zurück.

Dazu ist noch anzumerken, das die QUery einiges an interner Logik zu bieten hat, wenn du ein vernünftiges SQL Statement unter SQL einfügst, so Analysiert im Hintergrund die QUery das Statement und bildet automatisch SQL für Insert, Delete und Update. Diese werden dann bei Bedarf, siehe oben, verwendet. Damit da etwas sinnvolles herauskommt, braucht die Query Infos, weil ohne PK es zum Beispiel doubletten geben kann oder die Query nicht erkennt, das das Selectstatement einen Join beinhaltet und über mehrere Tabellen geht (besonders fies bei Views). Auch ist es deswegen wichtig etwaige Parameter wirklich zu verwenden und nicht über String gefrickel das irgendwie hinein zu pressen. Hexen und Vorhersehung kann die Query nämlich nicht. In so einem Moment, ist es besser die entsprechenden Statements für Insert, Delete und Updates selbst zu parametrieren.

Quellen:
https://www.datenbanken-verstehen.de/da ... kommandos/
https://www.freepascal.org/docs-html/fc ... state.html

Lazarus und Delphi sind in weiten Teilen SourceCode ähnlich (großteils kompatibel), das heisst aber nicht das die internen Funktion gleich sind. Bei ZEOS ist eine Gleichheit ziemlich hergestellt, aber nur für die Teile die ZEOS sind.
In der vorherigen Anwort von Dir (und von six1), würde es an der Verbindung zum DBGrid liegen, wenn es nicht funktioniert
Kurz gesagt ad 3: Du erstellst ein Datenset mit einem SQL Statement, zerstörst es dann, mit dem delete Statement, und willst dann mit dem SQL Statement weiterarbeiten, da du ja überschrieben hast. Mehr als einen Fehler zu werfen kann nicht erwartet werden. Warum du nicht einfach delete im Datenset mit gefolgten Post machen. Beim Append hast du es ja auch gemacht. Und zu deiner

Generell entweder über eine Query und die DBKomponenten ausnutzen oder alles zu Fuß über die Query direkt, dann verwende aber keine DBKomponenten.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Luckner
Beiträge: 88
Registriert: Sa 18. Jan 2020, 09:56
OS, Lazarus, FPC: Winux (L 2.2.0 FPC 3.2.2)
CPU-Target: Windows 64-Bit

Re: Fehler beim Löschen und Einfügen der Datensätze.

Beitrag von Luckner »

Hallo af0815,

dann, bitte ein Beispiel (besser mit aus Routine) zu Punkt 3. Dann verstehe ich es besser.

Gruß, Luckner.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6216
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: Fehler beim Löschen und Einfügen der Datensätze.

Beitrag von af0815 »

Das komplette Tutorial
https://wiki.freepascal.org/SQLdb_Tutorial0
Speziell hier
https://wiki.freepascal.org/SQLdb_Tutorial2 dort unter Summary procedure TForm1.DBGrid1KeyUp

Query
https://wiki.freepascal.org/Working_With_TSQLQuery
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Antworten