Autor Beitrag
stiff
Hält's aus hier
Beiträge: 3



BeitragVerfasst: So 01.05.05 18:36 
Hallo,
ich habe folgende Beispiel-Transaktion:

ausblenden 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 user profile iconChristian S.: Code- durch Delphi-Tags ersetzt.
Lemmy
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 792
Erhaltene Danke: 49

Windows 7 / 10; CentOS 7; LinuxMint
Delphi 7-XE10.1, VS 2015
BeitragVerfasst: 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:

ausblenden 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 Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: 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!)

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 612

WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
BeitragVerfasst: Mo 02.05.05 16:41 
user profile iconstiff 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 Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 792
Erhaltene Danke: 49

Windows 7 / 10; CentOS 7; LinuxMint
Delphi 7-XE10.1, VS 2015
BeitragVerfasst: 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



BeitragVerfasst: Di 03.05.05 09:14 
user profile iconstiff 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 534



BeitragVerfasst: 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



BeitragVerfasst: Di 03.05.05 10:18 
user profile iconAmiga-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 :gruebel:).
Amiga-Fan
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 534



BeitragVerfasst: 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



BeitragVerfasst: Sa 25.11.06 14:21 
user profile iconAmiga-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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 534



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 534



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 792
Erhaltene Danke: 49

Windows 7 / 10; CentOS 7; LinuxMint
Delphi 7-XE10.1, VS 2015
BeitragVerfasst: So 26.11.06 13:51 
Hi,

wenn Delphi sich beschwert, dass schon eine Transaktion gestartet ist, warum überprüfst Du das nicht vorher?

ausblenden Delphi-Quelltext
1:
2:
3:
if Transaction.InTransaction then
  Transaction.Commit;
Transaction.StartTransaction;


Lemmy
Amiga-Fan
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 534



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 792
Erhaltene Danke: 49

Windows 7 / 10; CentOS 7; LinuxMint
Delphi 7-XE10.1, VS 2015
BeitragVerfasst: So 26.11.06 19:51 
user profile iconAmiga-Fan hat folgendes geschrieben:
... die Transaktion theorethisch bereits abgeschlossen.


eben... theoretisch, aber nicht praktisch!


user profile iconAmiga-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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 534



BeitragVerfasst: 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:

ausblenden volle Höhe Delphi-Quelltext
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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3079
Erhaltene Danke: 9



BeitragVerfasst: So 26.11.06 20:54 
Was ist denn das für eine Funktion ? :shock:

Jetzt mal der Reihe nach :

user profile iconAmiga-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.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
  if not DM.Transaction.Active then // FormShow
    DM.Transaction.StartTransaction;
...
  if DM.Transaction.Active then // FormClose
    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 :

ausblenden Delphi-Quelltext
1:
2:
3:
4:
...
  if DM.Transaction.Active then begin // überflüsssig, sofern FormShow wie oben !
    DM.Transaction.Commit;            // speichern  
    DM.Transaction.StartTransaction;  // für nächste Eingaben Transaktion wieder starten

_________________
Gruß
Hansa
Amiga-Fan
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 534



BeitragVerfasst: 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