"Christmas - the time to fix the computers of your loved ones" « Lord Wyrm

SQL: Rollback Transaction funzt nicht

Chrissicom 14.06.2008 - 05:00 4202 5
Posts

Chrissicom

Rise of the Ryzen
Avatar
Registered: Jul 2006
Location: Falkensee
Posts: 1942
Code:
BEGIN TRANSACTION CreateEmployee
INSERT INTO Employee(LoginID,Title,Gender,....)
VALUES (@LoginID,@Title,@Gender,....)
INSERT INTO BankAccount (BankName,KTONR,BLZ,IBAN,BIC)
VALUES (@BankName,@KTONR,@BLZ,@IBAN,@BIC)
INSERT INTO BankAccountEmployee (EmployeeID,AccountID)
VALUES ((SELECT max(EmployeeID) FROM Employee),(SELECT max(AccountID) FROM BankAccount))
ROLLBACK TRANSACTION CreateEmployee
COMMIT TRANSACTION CreateEmployee
GO

Das ist eine Stored Procedure, allerdings meckert er an der ROLLBACK, COMMIT Syntax rum und ich verstehe nicht wieso. Im SQL Manager sagt er erstmal nix und lasst mich eine Stored Procedure mit dem Code erzeugen. Wenn ich das ganze von der Anwendung aber ausführen möchte und die Daten eintrage sagt er das die Commit Transaction Klausel keine corresponding Begin Transaction Klausel hat, aber das is doch blödsinn. Ich schreibe doch am Anfang BEGIN, und vorm Commit nen Rollback falls Fehler auftreten damit gar nix eingefügt wird und dann das Commit wieso findet er da die Begin Transaction Klausel nimmer? Wenn ich das Rollback wegmache geht's aber dann können halt unfertige Datensätze in der Datenbank landen was ich nich will.

Also wo is der Fehler???
Bearbeitet von Chrissicom am 14.06.2008, 11:56 (code tag added)

that

Moderator
Hoffnungsloser Optimist
Avatar
Registered: Mar 2000
Location: MeidLing
Posts: 11338
Eine Transaktion hat einen Anfang (BEGIN) und ein Ende (ROLLBACK *oder* COMMIT).
Du hast eine Transaktion, die du mit ROLLBACK beendest, und dann ein überflüssiges COMMIT.

(ein ROLLBACK ohne irgendeiner Bedingung am Ende ist allerdings wenig zweckmäßig, wenn du jemals irgendwelche Daten in die Datenbank füllen willst ;) )
Bearbeitet von that am 14.06.2008, 10:40

Chrissicom

Rise of the Ryzen
Avatar
Registered: Jul 2006
Location: Falkensee
Posts: 1942
Hmmm, also in den Beispielen auf MSDN steht aber wenn ich das nicht völlig falsch verstanden hab, das ein ROLLBACK in T-SQL zwischen BEGIN und COMMIT zu stehen hat. Wenn ich nur das ROLLBACK da hinschreibe ohne Bedingung, dann setzt er die Aktion wie du schon richtig feststellst immer zurück. Ich werde mal probieren sowas wie IF EXCEPTION != NULL davor zu setzen und poste dann hier rein wenn es so gehen sollte.

Was übrigens m.E. funktioniert:

BEGIN TRY
BEGIN TRAN T1
// ...
COMMIT TRAN T1
END TRY
BEGIN CATCH
ROLLBACK TRAN T1
END CATCH
GO

Also wie so ein schöner Try and Catch Block in C# oder Java. Das Problem dabei ist allerdings das er keinen Exception Code zurück gibt in diesem Fall , sondern nur das Rollback ausführt und somit das Error Handling das ich im Code Behind File programmiert habe nicht greift und nur eine "kann nicht eingefügt werden Meldung" anstatt des tatsächlichen Fehlers zurück gegeben wird.
Bearbeitet von Chrissicom am 14.06.2008, 11:27

semteX

begehrt die rostschaufel
Avatar
Registered: Oct 2002
Location: Pre
Posts: 14593
du führst alles aus und machst danach ein rollback....

hmm

wieso führt er nur jedes mal ein rollback aus?

natürlich musst du das rollback an ne bedingung hängen, exception oder selbst mit count oder ähnlichem nachkontrolliern.

und wie that schon sagte => was soll das commit noch commiten? die transaktion wurde doch mim rollback schon zerstört

es gibt so viele gute links zum thema pl/sql + transactions + exceptions, so schwer is das ned

Chrissicom

Rise of the Ryzen
Avatar
Registered: Jul 2006
Location: Falkensee
Posts: 1942
1. Benutze ich T-SQL und nicht PL/SQL
2. Habe ich ja nun schon eine Lösung gefunden wie das mit dem Rollback funzt

Wenn du dir das MSDN Beispiel anschaust für ROLLBACK dann steht das dort ohne Bedingung zwischen BEGIN und COMMIT. Da muss wohl für mich nicht ersichtlich im Text irgendwo stehen das man noch eine Bedingung braucht.

Jedenfalls ist das verbleibende Problem jetzt noch, das durch das Rollback die Exception Message die von der Transaktion eigentlich generiert werden würde "zerstört" wird. Das will ich aber vermeiden damit ich im C# Code über e.Exception.Message (e ist vom Typ object) den Fehler auslesen kann damit ich dem Benutzer eine Nachricht über den genauen Fehler geben kann, anstatt einfach nur die plumpe Aussage "hat nicht geklappt".

Code: PHP
Feedback.Text = "Es konnte leider keine Änderung vorgenommen werden. Setz dich bitte mit dem Administrator in Verbindung." + " (" + DateTime.Now + ")";
                    if (e.Exception != null) /* We want to avoid showing Server Error Pages to the user so we output the error text to a label */
                    {
                        Feedback.Text = e.Exception.Message;
                        e.ExceptionHandled = true;
                    }
                    break;

Durch das Rollback bleibt e.Exception eben null, das will ich aber nicht wenns nicht zum COMMIT kommt. Ein simples PRINT @@ERROR im Catch Block bringt leider nix.

Triple-X

Addicted
Avatar
Registered: Feb 2001
Location: Pregarten (OÖ)
Posts: 485
Du könntest ja im Catch Block nach dem Rollback selbst einen Fehler auslösen mit RAISERROR

Die Message kannst du dir ja selbst zusammen basteln aus ERROR_LINE, ERROR_MESSAGE, ERROR_NUMBER, ERROR_PROCEDURE, ERROR_SEVERITY, ERROR_STATE

EDIT:
noch 2 msdn links dazu:
http://technet.microsoft.com/en-us/...y/ms175976.aspx
http://msdn.microsoft.com/en-us/library/ms178592.aspx

hth
Bearbeitet von Triple-X am 16.06.2008, 13:48
Kontakt | Unser Forum | Über overclockers.at | Impressum | Datenschutz