Thema: Delphi Commit geht nicht (SQL)

Einzelnen Beitrag anzeigen

urs.liska

Registriert seit: 6. Aug 2003
Ort: Freiburg
195 Beiträge
 
Delphi 6 Professional
 
#21

Re: Commit geht nicht (SQL)

  Alt 22. Aug 2003, 11:22
Verständnisfrage: Du willst eingeben, dass Artikel in das Lager eingestellt werden, richtig (wenn es auch um rausnehmen geht, verstehe ich nicht, wozu dann das Insert gut sein sollte)?
Ist LAGER8.ID_ART der Fremdschlüssel, der auf den Artikel zeigt? Und die Artikeltabelle hat ID als Primärschlüssel? So sieht das zumindest im ersten Teil des Postings aus (wenn du 'aendern' ermittelst).
Ich nehme auch an, dass ArtDS während des ganzen Vorgangs geöffnet ist und GesMenge eine lokale Variable ist, die irgendwie aus ArtDS o.ä. ermittelt wird.

Wenn das so ist, musst Du aber beim Insert sagen: "INSERT INTO LAGER8 (ID_ART, MENGE)...", denn Du willst ja die Artikelnummer in das Fremdschlüsselfeld eintragen und nicht in den Primärschlüssel der Lager-Tabelle. (Ich nehme an, Du hast für LagDS eine Regelung für das AutoInc-Feld?). Ich weiß nicht, ob dieser Fehler das ungewöhnliche Verhalten Deiner Anwendung verursacht, aber es ist auf jeden Fall ein Fehler, den Du ausmerzen musst (vielleicht hast Du ihn nur noch nicht bemerkt, weil ja keine Daten eingetragen werden).

Und: bei der UPDATE-Anweisung fehlt unbedingt die WHERE-Klausel (WHERE ID_ART = 'aktuelle Artikelnummer'), sonst änderst Du alle Datensätze!!! statt ID_ART kannst Du auch nach ID suchen und einen Wert eintragen, den du in der ersten Abfrage zwischengespeicherthast:
Delphi-Quellcode:
lagDS.open;
if not LagDS.IsEmpty then
begin
  aendern := true;
  LagId := LagDS.FieldByName('ID').AsInteger;
end;
...
  LagDS.SelectSQL.Add ('UPDATE LAGER8 SET MENGE=MENGE-');
  LagDS.SelectSQL.Add (IntToStr (GesMenge));
  LagDS.SelectSQL.Add ('WHERE ID = ' + IntToStr(LagId));
Außerdem: was kiar sagt, stimmt: Transaktionen sollten so kurz wie möglich sein. Also nicht beim Öffnen des Fensters starten und beim Schließen beenden. Die Transaktion sollte vor Beginn des zusammenhängenden Vorgangs gestartet und nach Abschluss desselben beendet werden. Sie dient nur dazu, zu garantieren, dass die zusammenhängenden Buchungen nicht nur teilweise durchgeführt werden. Transaktionen sind nicht dazu da, bei Datenbanken so etwas wie ein "Dokument" zu simulieren, das erst am Ende der Sitzung gespeichert wird! Wenn Dir das wichtig ist, solltest Du so etwas wie einen Log-Mechanismus verwenden, der alle Änderungen während der Sitzung speichert, um diese ggfs. rückgängig machen zu können. Im Prinzip geht das auch mit Cached Updates oder ClientDataSets...

Wenn Du sicher weißt, dass Deine Anwendung nur von sehr wenigen Benutzern oder gar nicht im Netzwerk ausgeführt wird, kannst Du Dich aber auch über diese Regeln hinwegsetzen, da sie vor allem dann ins Gewicht fallen, wenn gleichzeitig verschiedene Transaktionen (z.B. von verschiedenen Usern) aktiv sind.

Es gibt noch einen Aspekt. IBX (ich nehme an, Du nimmst die) regelt Transaktionen automatisch, wenn Du sie nicht explizit steuerst. D.h. die Transaktion ist (so wie Du es bisher machst) nur dann während der ganzen Sitzung aktiv, wenn sie den Datenmengen auch korrekt zugeordnet ist (Also IBDatabase.DefaultTransaction auf die Transaktion zeigt und die DataSets auf die entsprechende Datenbank). Wenn hier etwas nicht klar sein sollte, ist in jedem Fall mit ungewöhnlichem Verhalten der Anwendung zu rechnen.

Also:
1) ich würde es dennoch mit der IBSQL-Komponente versuchen, das entspricht einfach dem, was Du tun willst. Ansonsten probier mal, was mit Post passiert (würde mich aber wundern, wenn es doch funktioniert).
2) würde ich die beiden Fehler in den SQL-Anweisungen korrigieren
3) würde ich die Transaktion direkt in die Routine legen
Und ich würde die Veränderungen einzeln machen und testen, nicht alles auf einmal, sonst weißt Du nicht, was passiert ist.

Viel Erfolg
Urs

P.S.
nach nochmaligem Durchlesen fällt mir auf, dass ich keine wirkliche Antwort auf das eigentlich ungewöhnliche Verhalten der Anwendung gefunden habe. Aber ich bin ziemlich sicher, dass dieses mit der falschen (? oder doch zumindest unorthodoxen Verwendung von SelectSQL zu tun hat). Und die Fehler, die ich angesprochen habe, würden in jedem Fall zu Tage treten, wenn Du Dein erstes Problem gelöst hast.
  Mit Zitat antworten Zitat