![]() |
Datenbank: MS SQL Server • Version: 2005 • Zugriff über: ADO
Unterschiedliches Verhalten bei Transaktionen
Hallo Zusammen,
hat jemand von Euch ne Ahnung, warum folgendes Verhalten auftritt bzw. wie ich das ändern kann? Ich verwende Delpi 2007 und bin über eine ADOConnection und ein ADODataSet mit einem MS SQL-Server 2005 verbunden. Folgende zwei Szenarien verhalten sich unterschiedlich, warum? I.
II.
Soll bzw. muß das so sein? Und wer ist an diesem Verhalten Schuld : der SQL-Server, ADO oder Delphi ? PS: Das Verhalten in Szenario I konnte ich übrigens nur bei SMALLDATETIME feststellen, bei DATETIME > 31.12.9999 oder SMALLINTEGER > 32767 z.B. verhält sich das ganze genau wie in Szenario II. Gruß Micha |
Re: Unterschiedliches Verhalten bei Transaktionen
Hallo,
schau mal in die Logfiles des SQL-Servers, ob der da was meldet. Ausgehend von Deinem PS schließe ich auf einen Fehler im SQL-Server. Stephan |
Re: Unterschiedliches Verhalten bei Transaktionen
Hallo Stephan,
ich hab gleich mal nachgeschaut, konnte aber nichts Auffälliges erkennen. Die letzten Einträge stammen vom Hochfahren des Servers. Gruß Micha |
Re: Unterschiedliches Verhalten bei Transaktionen
Hallo,
SQL-Server 2005: Habe folgendes probiert:
SQL-Code:
Ergebnis sollte stimmen, bei Dir auch, dann ist's nicht die Datenbank.
/*
create table test ( a smalldatetime, b smallint, c VarChar(20) ) create unique index c on test (c); */ begin transaction delete from test commit transaction begin transaction insert into test (a,b,c) values ('01.01.1999',32677,'test'); insert into test (a,b,c) values ('01.01.2099',32677,'test2000'); insert into test (a,b,c) values ('01.01.1999',32677,'test'); insert into test (a,b,c) values ('01.01.1999',326770,'test'); insert into test (a,b,c) values ('01.01.1999',32677,'test1'); commit transaction select * from test 1999-01-01 00:00:00 32677 test 1999-01-01 00:00:00 32677 test1 Kannst Du an der Exception erkennen, wer sie genau wirft? Poste sie ggfls. mal hier. Die ADOConnection hat ein "Fehler"-Array, gib das mal aus, eventuell gibt es da mehr Infos:
Delphi-Quellcode:
Ausgehend von Deiner Beschreibung ist für mich nicht zu erkennen, wo Du im Quelltext das Commit machst, ist sichergestellt, dass es auch bei jeder Ausnahme ausgeführt wird?
Var
i : Integer; begin for i := 0 to ADOConnection.Errors.Count - 1 do begin Writeln(ADOConnection.Errors.Item[i].Number); Writeln(ADOConnection.Errors.Item[i].Source); Writeln(ADOConnection.Errors.Item[i].Description); Writeln(ADOConnection.Errors.Item[i].SQLState); Writeln(ADOConnection.Errors.Item[i].NativeError); end; end; Stephan |
Re: Unterschiedliches Verhalten bei Transaktionen
Hallo Stephan,
1. Dein SQL-Skript liefert bei mit die selben Ergebnisse 2. es wird immer ein CommitTrans ausgeführt - der Debugger kommt jedenfalls durch 3. das Fehler-Array der ADOConnection hat folgenden Inhalt: -2147217900 Microsoft OLE DB Provider for SQL Server smalldatetime-Überlauffehler bei der Konvertierung des datetime-Datentyps in den smalldatetime-Datentyp. 42000 298 Gruß Micha |
Re: Unterschiedliches Verhalten bei Transaktionen
Hallo Micha,
Wenn der Debugger immer am Commit vorbei kommt, würde dies heißen, dass die Schnittstelle entweder alle oder keine Daten durchläßt, bzw. selbst ein Rollback macht, sofern ein von ihr entdeckter Fehler auftritt. Dies würde auch das von Dir beschriebene Verhalten erklären. Kann man beim SQL-Server irgendwo mitgucken, welcher Client gerade was macht? Habe da keine Ahnung, bei Oracle ist's meines Wissens nach möglich. Wenn's geht, könntest Du mal schauen, was alles von Deinem Programm an der Datenbank ankommt (von dem Du eventuell garnicht weißt, dass es von Deinem Programm kommt, das wären dann die "Selbständigkeiten" der Schnittstelle). Leider gelingt es mir nicht anhand der Fehlermeldungen zu unterscheiden, ob sie von der Datenbank oder von der Schnittstelle kommen. Bei Google finde ich auch nichts zu dem Thema (ausser Deinem vorherigen Post :wink: (Boooooh ist Google schnell)). Da wirst Du wohl im Programm sicherstellen müssen, dass der Datentyp in Ordnung ist. Stephan |
Re: Unterschiedliches Verhalten bei Transaktionen
Hallo Stephan,
hab mir mal den Verkehr zwischen meiner Testapplikation und dem SQL-Server mittels dem SQL-Profiler angeschaut. Sehr eigenartig: - wenn ich nem SMALLINT-Feld einen SMALLINT-Wert zuweise und dann ein Post mache, wird die Anweisung angezeigt - wenn ich nem SMALLINT-Feld einen INTEGER-Wert zuweise und dann ein Post mache, wird diese Anweisung nicht angezeigt --> die 1.Zeile ist danach in der Tabelle drin, die Zweite nicht - beim SMALLDATETIME-Feld wird die Anweisung sowohl bei nem SMALLDATETIME-Wert als auch bei nem DATETIME-Wert angezeigt, --> im Nachhinein ist allerdings keiner der beiden Werte in der Tabelle Bei beiden Test ist aber auch kein zusätzliches Rollback zusehen, allerdings sehe ich auch das "begin transaction" nicht ??? PS: Wenn ich das mit dem Integer mache, steht auch gar nichts im Error-Record drin !!! So als ob Delphi das Post gar nicht erst ausführen würde und schon eine Exception auslösen tut, bevor es die Daten überhaupt zum SQL-Server schickt. Würde erklären, daß hier kein Rollback ausgeführt wird, da so am SQL-Server ja auch kein Fehler vorliegt. Gruß Micha |
Re: Unterschiedliches Verhalten bei Transaktionen
Hallo Micha,
sorry, aber das kommt mir jetzt spanisch vor: Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Habe das bei mir mal ausprobiert, kann im SQL-Profiler (wusste bis eben garnicht, dass es sowas gibt :oops:) die Transaktionen sehen. Allerdings habe ich in den Eigenschaften der Ablaufverfolgung die Checkbox "Alle Ereignisse" anzeigen aktiviert und dann im Zweig "Transactions" alles aktiviert. Wieso ist hier nachher ein Datensatz in der Datenbank?
SQL-Code:
wenn das in einer Transaktion abläuft, hätte ich hier keinen erwartet. Das ist meiner Meinung nach ein Fehler der Datenbank, entweder alles aus einer Transaktionsklammer oder nichts.
begin transaction
insert into test (a,b,c) values ('01.01.1999',32677,'test'); insert into test (a,b,c) values ('01.01.2099',32677,'test2000'); --insert into test (a,b,c) values ('01.01.1999',32677,'test'); --insert into test (a,b,c) values ('01.01.1999',326770,'test'); --insert into test (a,b,c) values ('01.01.1999',32677,'test1'); commit transaction Hier das gleiche Verhalten:
SQL-Code:
Auch das ist meiner Meinung nach nicht korrekt.
begin transaction
insert into test (a,b,c) values ('01.01.1999',32677,'test'); insert into test (a,b,c) values ('01.01.1999',326770,'test'); commit transaction Korrekt wäre:
SQL-Code:
und anschließend ist der erste Datensatz in der Datenbank, aber das weicht jetzt vom Thema ab, allerdings liegt für meine Begriffe die Vermutung nahe, dass Dein Problem mit diesem Verhalten der Datenbank im Zusammenhang steht.
begin transaction
insert into test (a,b,c) values ('01.01.1999',32677,'test'); commit transaction begin transaction insert into test (a,b,c) values ('01.01.1999',326770,'test'); commit transaction Das von Dir geschilderte Problem wird mir in diesem Zusammenhang nicht klarer bzw. habe ich momentan keine Ahnung, wie Du um Dein Problem herumkommen kannst (von richtig lösen mag ich garnicht sprechen). Wie soll man konsistente Daten sicherstellen, wenn sich die Datenbank nicht "erwartungskonform" verhält und zwischen der eigenen Applikation und der Datenbank noch eine Schnittstelle steckt, zu deren "Verhalten im Fehlerfalle" keine Informationen vorliegen? Habe keine Idee mehr, die Dir bei der Problemlösung helfen könnte. Zitat:
Delphi-Quellcode:
mit dem SQL:
procedure TForm1.Button1Click(Sender: TObject);
Var i : Integer; begin ADOConnection1.Open; ADOQuery1.SQL.Clear; Memo1.Lines.Clear; Try ADOQuery1.SQL.Text := memo2.Text; ADOConnection1.BeginTrans; ADOQuery1.ExecSQL; ADOConnection1.CommitTrans; Except on e : EOleException do begin ADOConnection1.RollbackTrans; for i := 0 to ADOConnection1.Errors.Count - 1 do begin Memo1.Lines.Add(IntToStr(ADOConnection1.Errors.Item[i].Number)); Memo1.Lines.Add(ADOConnection1.Errors.Item[i].Source); Memo1.Lines.Add(ADOConnection1.Errors.Item[i].Description); Memo1.Lines.Add((ADOConnection1.Errors.Item[i].SQLState)); Memo1.Lines.Add(IntToStr(ADOConnection1.Errors.Item[i].NativeError)); end; end; on e : Exception Do begin ADOConnection1.RollbackTrans; ShowMessage(e.Message); end; end; ADOConnection1.Close; end;
SQL-Code:
In diesem Fall habe ich anschließend zwei Datensätze in der Datenbank.
delete from test ;
insert into test (a,b,c) values ('01.01.1999',32677,'test'); insert into test (a,b,c) values ('01.01.2099',32677,'test2000'); insert into test (a,b,c) values ('01.01.1999',32677,'test'); insert into test (a,b,c) values ('01.01.1999',326770,'test'); insert into test (a,b,c) values ('01.01.1999',32677,'test1'); Offensichtlich hast nicht Du ein Problem, sondern alle haben ein Problem :cry: Kannst Du das Ganze gegen eine andere Datenbank testen (nicht SQL-Server)? Stephan |
Re: Unterschiedliches Verhalten bei Transaktionen
Hallo Stephan,
vielen Dank für Deine Bemühungen. Ich werde jetzt aus allen SMALLDATETIME-Feldern DATETIME-Felder machen, daß wenigstens bei allen Feldern das selbe vorhersehbare Verhalten im Fehlerfall auftritt. Ob's nun richtig ist oder falsch ... Einen anderen SQL-Server hab ich momentan nicht zur Verfügung und leider auch keine Zeit mir eine weitere Testumgebung zu schaffen. Vielen Danken nochmal. Gruß Micha |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:26 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz