THROW (Mit und ohne Semikolon)

Hier kann ich nicht so richtig reinschreiben: Neuerung in 2012, denn es kommt fatal auf die Schreibweise an.

Ausgehend von dem Connect-Beitrag von Erland Sommarskog möchte ich hier kurz die Problematik erläutern.

Aus der Online-Doku

Hier finden wir die Hinweise: Löst eine Ausnahme aus und übergibt die Ausführung an einem CATCH-Block eines TRY…CATCH-Konstrukts in SQL Server 2012. bzw. Auf die Anweisung vor der THROW-Anweisung muss als Anweisungsabschlusszeichen das Semikolon (;) folgen.

Leider wird dort nicht erwähnt, dass THROW kein reserviertes Wort ist. Man kann es also auch problemlos vor SQL Server 2012 verwenden, nur eben mit anderer Wirkung.

Beispiele

Das folgende Skript läuft auch problemlos unter SQL Server 2008!

BEGIN TRY
BEGIN TRANSACTION
SAVE TRANSACTION
THROW

SELECT 1/0
COMMIT TRANSACTION
END
TRY
BEGIN CATCH
IF @@trancount > 0 ROLLBACK TRANSACTION
THROW
END CATCH
GO
SELECT @@trancount AS trancount

Man beachte die Farbgebung für THROW. Das Wort wird im gleichen Farbton dargestellt wie trancount am Ende.

Das nächste Beispiel läuft unter SQL Server 2012 und verwendet THROW wirklich so, wie wir uns das wünschen. Im Management Studio vor 2012 wird THROW jetzt als Syntax-Fehler erkannt, im Management Studio ab 2012 in blau dargestellt.

BEGIN TRY
BEGIN TRANSACTION

SELECT
1/0
COMMIT TRANSACTION
END
TRY
BEGIN CATCH
IF @@trancount > 0 ROLLBACK TRANSACTION ;
THROW
END CATCH
GO
SELECT @@trancount AS trancount;

THROW wird jetzt in blau dargestellt und macht genau das, was wir wollen!
Aber Vorsicht: Nicht das Semikolon hinter ROLLBACK TRANSACTION weglassen:

BEGIN TRY
BEGIN TRANSACTION

SELECT
1/0
COMMIT TRANSACTION
END
TRY
BEGIN CATCH
IF @@trancount > 0 ROLLBACK TRANSACTION
THROW
END CATCH
GO
SELECT @@trancount AS trancount;

Jetzt erhalten wir eine Fehlermeldung:

Meldung 6401, Ebene 16, Status 1, Zeile 8
Cannot roll back THROW. No transaction or savepoint of that name was found.

Was ist hier passiert?

Ohne das Semikolon hat THROW plötzlich seine Eigenschaft als Anweisung verloren und ist jetzt nur noch ein simpler Name für einen Savepoint. Dass es den gar nicht gibt und dieser Fehler evtl. erst sehr spät entdeckt wird, hinterlässt einen etwas schalen Beigeschmack bei der guten Idee des THROW.

Aber wir können ja beim Connect-Item von Erland mit voten!