Autor |
Beitrag |
stiff
Hält's aus hier
Beiträge: 3
|
Verfasst: So 01.05.05 18:36
Hallo,
ich habe folgende Beispiel-Transaktion:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| ... if not m_update.Transaction.InTransaction then m_update.Transaction.StartTransaction;
if not m_update.ExecuteSQL('alter table abnehmer add mitglied char(1)') then goto L_ERROR; if not m_update.ExecuteSQL('update abnehmer set mitglied = ''N''') then goto L_ERROR; ... m_update.Transaction.Commit;
L_ERROR: m_Update.Transaction.Rollback; |
Das Feld 'mitglied' wird in die Tabelle eingefuegt, aber beim Updaten des Feldes kommt eine Fehlermeldung (conversion error from string 'N')!
Muss man wirklich nach jedem "alter table ..." ein 'commit' machen oder übersehe ich da was?
Die Transaktion sollte normalerweise ja dafür da sein, dass man mehrere Anweisungen entweder ganz oder gar nicht ausführt.
Bitte um Ratschläge
Gruß
stiff
Moderiert von Christian S.: Code- durch Delphi-Tags ersetzt.
|
|
Lemmy
      
Beiträge: 792
Erhaltene Danke: 49
Windows 7 / 10; CentOS 7; LinuxMint
Delphi 7-XE10.1, VS 2015
|
Verfasst: So 01.05.05 20:08
Hi,
ich würde Änderungen an der Struktur nicht mit DML-Anweisungen mischen. Ich empfehle Dir zudem, auf goto zu verzichten. Der Fehler hat meiner Meinung nach aber nichts mit der Transaktionssteuerung zu tun.... Versuch mal folgendes:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| if not m_update.Transaction.InTransaction then m_update.Transaction.StartTransaction;
try m_update.ExecuteSQL('alter table abnehmer add mitglied char(1)'); m_update.ExecuteSQL('update abnehmer set mitglied = '#39'N'#39); ... m_update.Transaction.Commit; except m_Update.Transaction.Rollback; end; |
Lemmy
|
|
stiff 
Hält's aus hier
Beiträge: 3
|
Verfasst: Mo 02.05.05 16:30
Hallo Lemmy,
habe deinen Vorschlag implementiert, es kommt aber trotzdem immer noch dieselbe Fehlermeldung.
Das Vermischen von DDL- und DML-Anweisungen wäre für mich eines der wichtigsten Punkte bei Transaktionen,
da dies bei anderen Datenbanken (z.B. PostgreSQL) ja auch funktioniert.
Ich verwende eine TIBQuery für die SQL-Anweisung. Wenn ich der Query die Parameter manuell zuweise (also z.B. m_IBQuery.Params[0] := 'N'), dann kommt keine Fehlermeldung, jedoch bleibt die erhoffte Wirkung der SQL-Anweisung aus. (im obigen Beispiel wird Feld 'mitglied' nicht gesetzt!)
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| function TUpdate.ExecuteSQL(sql:string): boolean; begin m_IBQuery.Close; m_IBQuery.SQL.Clear; m_IBQuery.SQL.Text := sql; try m_IBQuery.ExecSQL; ExecuteSQL:=True except on E:Exception do begin MessageDlg(E.Message,mtError,[mbOK],E.HelpContext); ExecuteSQL:=False end end end; |
Ist TIBQuery die ideale Komponente zum Ausführen von SQL-Statements oder gibt es da Komponenten, welche geeigneter wären?
|
|
Stefan.Buchholtz
      
Beiträge: 612
WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
|
Verfasst: Mo 02.05.05 16:41
stiff hat folgendes geschrieben: | Hallo Lemmy,
habe deinen Vorschlag implementiert, es kommt aber trotzdem immer noch dieselbe Fehlermeldung.
Das Vermischen von DDL- und DML-Anweisungen wäre für mich eines der wichtigsten Punkte bei Transaktionen,
da dies bei anderen Datenbanken (z.B. PostgreSQL) ja auch funktioniert.
|
DIe meisten Datenbanken, sogar Oracle und soweit ich weiss auch Interbase untestützen keine Transaktionen bei DDL-Anweisungen. Jede DDL-Anweisung wirkt als implizites Commit für vorherige DML-Anweisungen.
Stefan
|
|
stiff 
Hält's aus hier
Beiträge: 3
|
Verfasst: Mo 02.05.05 18:20
Dann werde ich in diesem Fall wohl oder übel ohne Transaktionen auskommen müssen ...
Danke trotzdem für die Hinweise!
stiff
|
|
Lemmy
      
Beiträge: 792
Erhaltene Danke: 49
Windows 7 / 10; CentOS 7; LinuxMint
Delphi 7-XE10.1, VS 2015
|
Verfasst: Di 03.05.05 07:35
Guten Morgen,
ja, es gibt wesentlich bessere Komponenten als TIBTable und TIBQuery. Diese wurden nur zu Umstellungszwecken (von BDE auf IBX) eingeführt und haben eigentlich sonst keinen Wert. Verwende entweder eine TIBDataSet oder eine TIBSQL (die gibt aber keine Werte zurück).
Lemmy
|
|
MagicAndre1981
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 03.05.05 09:14
stiff hat folgendes geschrieben: |
Dann werde ich in diesem Fall wohl oder übel ohne Transaktionen auskommen müssen ...
|
Das geht beim Interbase/Firebird wegen der MGA gar nicht. Sogar zum Lesen von Daten musst du eine Transaktion starten!
|
|
Amiga-Fan
      
Beiträge: 534
|
Verfasst: Di 03.05.05 09:36
Zitat: | Das geht beim Interbase/Firebird wegen der MGA gar nicht. Sogar zum Lesen von Daten musst du eine Transaktion starten! |
wie meinst du das? Muss man auch bei Select-Statements eine Transaktion machen? Bei mir hat es auch so funktioniert.
|
|
MagicAndre1981
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 03.05.05 10:18
Amiga-Fan hat folgendes geschrieben: | Zitat: | Das geht beim Interbase/Firebird wegen der MGA gar nicht. Sogar zum Lesen von Daten musst du eine Transaktion starten! |
wie meinst du das? Muss man auch bei Select-Statements eine Transaktion machen? Bei mir hat es auch so funktioniert. |
Dann wird die Transaktion bei automatisch gestartet worden sein. Bei den IBX - Komponenten gibts die Option "AutoStartTransaction" (oder so ähnlich  ).
|
|
Amiga-Fan
      
Beiträge: 534
|
Verfasst: Sa 25.11.06 00:12
warum muß man zum lesen eine Transaktion starten? habe wieder PRobleme damit...
_________________ - Leg dich nie mit einem Berufsprogrammierer an
- Wahre Profis akzeptieren keine einfachen Lösungen
|
|
MagicAndre1981
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 25.11.06 14:21
Amiga-Fan hat folgendes geschrieben: | warum muß man zum lesen eine Transaktion starten? |
Wegen der Multigenerationsarchitektur des Interbase/Firebird muss immer eine Transaktion gestartet werden, egal ob lesen oder etwas schreiben.
|
|
Amiga-Fan
      
Beiträge: 534
|
Verfasst: Sa 25.11.06 17:06
im Moment habe ich wieder das Problem, das er mir anzeigt das eine Transaktion schon aktiv ist. Das kann aber einfach nicht sein, ich habe absolut jedes starttransaction bereits schon mit commit abgeschlossen. Ich versteh das nicht, ob das vielleicht damit zusammenhängt das ich die tibquery und ibx allgemein mit Firebird 1.5.3 benutze? Wie würde das beim lesen denn aussehen sollen?
Lesen:
starttransaction
open
commitretaining bzw. rollback
----------
Schreiben:
starttransaction
execsql
commit bzw rollback
Muß das so aussehen?
_________________ - Leg dich nie mit einem Berufsprogrammierer an
- Wahre Profis akzeptieren keine einfachen Lösungen
|
|
UGrohne
      

Beiträge: 5502
Erhaltene Danke: 220
Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
|
Verfasst: Sa 25.11.06 18:23
Ein CommitRetaining bedeutet, dass zwar committed wird, aber die Transaktion immer noch offen bleibt. Schau mal nach, ob Du bei den IBTransactions als DefaultAction CommitRetaining angegeben hast. Das kann diese Meldung hervorrufen.
|
|
Amiga-Fan
      
Beiträge: 534
|
Verfasst: Sa 25.11.06 18:51
nein, commitretaining steht nicht drin, sondern commit.
wenn ich fürs lesen ein einfaches commit mache (statt commitretaining) hatte ich das Problem das anschließend keine Daten in der Query mehr drin waren.
_________________ - Leg dich nie mit einem Berufsprogrammierer an
- Wahre Profis akzeptieren keine einfachen Lösungen
|
|
Lemmy
      
Beiträge: 792
Erhaltene Danke: 49
Windows 7 / 10; CentOS 7; LinuxMint
Delphi 7-XE10.1, VS 2015
|
Verfasst: So 26.11.06 13:51
Hi,
wenn Delphi sich beschwert, dass schon eine Transaktion gestartet ist, warum überprüfst Du das nicht vorher?
Delphi-Quelltext 1: 2: 3:
| if Transaction.InTransaction then Transaction.Commit; Transaction.StartTransaction; |
Lemmy
|
|
Amiga-Fan
      
Beiträge: 534
|
Verfasst: So 26.11.06 16:25
nach jedem starttransaction mache ich bereits ein commit, wenn ich dann wieder ein starttransaction mache ist somit die Transaktion theorethisch bereits abgeschlossen.
das was du gezeigt hast, habe ich bereits versucht. Bei execsql erhielt ich dann eine Fehlermeldung
_________________ - Leg dich nie mit einem Berufsprogrammierer an
- Wahre Profis akzeptieren keine einfachen Lösungen
|
|
Lemmy
      
Beiträge: 792
Erhaltene Danke: 49
Windows 7 / 10; CentOS 7; LinuxMint
Delphi 7-XE10.1, VS 2015
|
Verfasst: So 26.11.06 19:51
Amiga-Fan hat folgendes geschrieben: | ... die Transaktion theorethisch bereits abgeschlossen. |
eben... theoretisch, aber nicht praktisch!
Amiga-Fan hat folgendes geschrieben: |
das was du gezeigt hast, habe ich bereits versucht. Bei execsql erhielt ich dann eine Fehlermeldung |
Und....??? OutOfMemory? Äpfel nicht gefunden? Birnen faul? oder soll ich weiterraten? Du kannst auch stopp rufen sobald ich die richtige Fehlermeldung geraten habe.... 
|
|
Amiga-Fan
      
Beiträge: 534
|
Verfasst: So 26.11.06 20:07
Zitat: | eben... theoretisch, aber nicht praktisch! |
wieviele commits muß ich denn machen, um da sicherzugehen? oder würdest du eher sowas wie
while transaction.intransaction do begin
end;
machen? Vor dem starttransaction oder nach dem commit?
im moment erhalte ich immer die meldung "Transaktion ist nicht aktiv", und das immer beim 2. Durchlaufen dieser Routine, beim commit:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38:
| try DBQuery.database.close; DBQuery.database.open;
if not DBQuery.database.Connected then begin DBQuery.database.open; if not DBQuery.database.Connected then begin DBQuery.database.open; if not DBQuery.database.Connected then begin result:=false; exit; end; end; end;
if assigned(dbtransaction) then DBQuery.Transaction:=DBTransaction; except result:=false; exit; end;
if assigned(dbtransaction) then DBTransaction.StartTransaction; try with DBQuery do begin close; if trim(DBQuery.SQL.text)<>trim(SQLStr) then begin sql.clear; sql.add(SQLStr); end; if pos('INSERT',ansiuppercase(SQLStr))>0 then begin [..] end; execsql; end; if assigned(dbtransaction) then DBTransaction.Commit; |
_________________ - Leg dich nie mit einem Berufsprogrammierer an
- Wahre Profis akzeptieren keine einfachen Lösungen
|
|
hansa
      
Beiträge: 3079
Erhaltene Danke: 9
|
Verfasst: So 26.11.06 20:54
Was ist denn das für eine Funktion ?
Jetzt mal der Reihe nach :
Amiga-Fan hat folgendes geschrieben: | ..wieviele commits muß ich denn machen, um da sicherzugehen? |
Lediglich eines. Geht das schief, dann liegt sonstwo ein Fehler vor und auch while etc. nützt dann nichts mehr. Ich nehme mal an, du benutzt ein Form, um Daten einzugeben.
Delphi-Quelltext 1: 2: 3: 4: 5:
| if not DM.Transaction.Active then DM.Transaction.StartTransaction; ... if DM.Transaction.Active then DM.Transaction.Commit; |
Mehr ist das nicht. Du kannst das genausogut in einen "Speichern"-Button verfrachten. Dann müßte zusätzlich noch in das OnClick :
Delphi-Quelltext 1: 2: 3: 4:
| ... if DM.Transaction.Active then begin DM.Transaction.Commit; DM.Transaction.StartTransaction; |
_________________ Gruß
Hansa
|
|
Amiga-Fan
      
Beiträge: 534
|
Verfasst: So 26.11.06 21:17
nein ich benutze ein datamodul, in dem diese Funktion ist, und dieser Funktion übergebe ich den sql-befehl. Der Funktion übergebe ich die Query und die Transaktion (da mein Programm 2 austauschbare Datenbanken verwaltet).
wie man sieht, mache ich in dieser Funktion ein starttransaction und commit. Wenn ich übrigens if assigned(dbtransaction) then weglasse, bleibt das problem vorhanden...
naja ich weiß nicht, woran es liegt. Imho ist dieser code richtig...
_________________ - Leg dich nie mit einem Berufsprogrammierer an
- Wahre Profis akzeptieren keine einfachen Lösungen
|
|