Welcome Guest, you are in: Anmelden

CP Wiki

RSS RSS

Navigation



  1. Administration

Suche im wiki
»
 » Startseite » netFrame als Plattform Menü » Tipps und Tricks » SQL Server Transaction und Error Handling | » Erweiterte Suche

  1. Einleitung
  2. Transaktionen
  3. Geschachtelte Transaktionen
  4. Save TRAN und Save Points
  5. Error Handling





    ==Einleitung==
    Die folgenden Beispiele beziehen sich auf die Pubs Datenbank, welche bei jeder neuen Installation eines SQL Servers bereits vorhanden sind. Sollten Sie eine frische Installation der "Pubs" Datenbank benötigen, folgen Sie dem Text.


  6. Führen Sie den folgenden osql Befehl aus um die Pubs Datenbank zu finden, wir benutzen dazu die Stored Procedure sp_detach_db.


    osql -U sa -P "" -Q "exec sp_detach_db 'Pubs'"
  7. Löschen Sie die Datenbankdateien der "Pubs" Datenbank (pubs.mdf, pubs_log.ldf). Diese Dateien befinden sich im \Data Ordner.

  8. Die Neuinstallation der "Pubs" Datenbank benötigt das Instpubs.sql Skript.


    osql -U sa -P "" -i
    "C:\Program Files\Microsoft SQL Server\MSSQL\Install\InstPubs.sql"




    Nach oben





    ==Transaktionen==
    Transactions gruppieren eine Reihe von Aufgaben in eine einzelne. Jede Transaction beginnt mit einer bestimmten Aufgabe und endet erst dann wenn alle Aufgaben erfolgreich ausgeführt wurden. Wenn eine einzelne Aufgabe nicht ausgeführt werden kann, kann die Transaction nicht ausgeführt werden. Aus diesem Grund hat eine Transaction nur zwei Ergebnisse: Erfolg oder Fehler. Fehlerhafte Schritte ergeben eine fehlerhafte Transaction.



    Benutzer können zwei oder mehrere Transact-SQL in eine einzelne Transaction mit folgenden Anweisungen gruppieren:


  9. Begin Transaction
  10. Rollback Transaction
  11. Commit Transaction


    Läuft etwas mit den gruppierten Anweisungen schief, müssen alle Änderungen abgebrochen werden. Der Prozess um Änderungen umzukehren wird ROLLBACK genannt.

    Wenn alles sauber funktioniert werden alle Änderungen zusammen in die Datenbank aufgenommen. In der SQL Terminologie nennt man dies COMMIT.



    Hier ist ein kleines Beispiel für eine Transaction:



    USE pubs

DECLARE @intErrorCode INT

BEGIN TRAN UPDATE Authors SET Phone = '415 354-9866' WHERE au_id = '724-80-9391'

SELECT @intErrorCode =
ERROR
    IF (@intErrorCode <> 0) GOTO PROBLEM

    UPDATE Publishers
    SET city = 'Calcutta', country = 'India'
    WHERE pub_id = '9999'

    SELECT @intErrorCode = 
ERROR IF (@intErrorCode <> 0) GOTO PROBLEM COMMIT TRAN

PROBLEM: IF (@intErrorCode <> 0) BEGIN PRINT 'Unexpected error occurred!' ROLLBACK TRAN END

Bevor die Echtzeitverarbeitung startet sagt der Befehl BEGIN TRAN das alle folgenden Anweisungen als eine Transaction zu behandeln sind, gefolgt von zwei UPDATE Anweisungen. Wenn während der Ausführung keine Fehler auftreten werden diese Änderungen durch den Befehl COMMIT TRAN bestätigt und in die Datenbank geschrieben. Sollten jedoch Fehler auftreten wird die Ausführung bei PROBLEM weitergeführt. Nachdem der Server dem Benutzer eine Meldung ausgegeben hat, werden alle Änderungen rückgängig gemacht.

Nach oben

Geschachtelte Transaktionen

Der SQL Server erlaubt es Ihnen mehrere Transaktionen zu schachteln. Das bedeutet eine neue Transaktion kann gestartet werden wenn die vorherige noch nicht abgeschlossen ist. Transact-SQL ermöglicht es Ihnen mehrere Transaktion zu schachteln, hierzu wird der Befehl BEGIN TRAN verwendet. Die automatische Variable TRANCOUNT kann ausgeführt werden um das Level der Schachtelung aufzuheben 0 keine Verschachtelung, 1 indiziert eine Verschachtelung ein Level tiefer, usw..

Wird ein COMMIT Befehl gegen eine Transaktion außer die äußerste ausgeführt, werden keine Änderungen in die Datenbank geschrieben - es vermindert lediglich die automatische Variable TRANCOUNT. Ein ROLLBACK wiederum funktioniert unabhängig von dem Level in welchem es ausgeführt wird, es macht alles rückgängig unabhängig vom Verschachtelungslevel. Wenn ein verschachtelter COMMIT Befehl permanente Änderungen in die Datenbank geschrieben hat, kann ein äußerer ROLLBACK Befehl dies nicht mehr rückgängig machen.

Wenn Sie explizit eine Transaktion starten erhöht sich der Zähler der automatischen Variable TRANCOUNT von 0 zu 1 wenn Sie mit einem COMMIT Befehl bestätigen, der Zähler verringert sich um 1 wenn Sie einen ROLLBACK Befehl ausführen. Wie Sie sehen ist das Verhalten von COMMIT und ROLLBACK nicht symmetrisch, wenn Sie Transaktionen verschachteln vermindert COMMIT das Verschachtelungslevel immer um 1 wie Sie in Abbildung 1 sehen können. Der ROLLBACK Befehl auf der anderen Seite widerruft die komplette Transaction (Abbildung 2). Die Ungleichmäßigkeit zwischen COMMIT und ROLLBACK ist der Schlüssel um Fehler in verschachtelten Transaktionen zu handhaben.

Bild

Abbildung 1: Ein COMMIT gleicht immer ein BEGIN TRANSACTION durch vermindern des Versachtelungszähler um 1 aus.

Bild

Abbildung 2: Ein einzelnes ROLLBACK löst die gesamte Transaktion auf.

Wie Sie in Abbildung 1 und 2 sehen können, können Sie Transaktionen verschachteln und die automatische Variable TRANCOUNT benutzen um das Level zu bestimmen. Sie haben außerdem gelernt, dass sich COMMIT und ROLLBACK nicht symmetrisch verhalten:

COMMIT vermindert nur das Level der TRANCOUNT Variable um 1.
ROLLBACK setzt das Level der TRANCOUNT Variable auf 0.

Dies hat die Auswirkung das eine Transaktion nie komplett ausgeführt wird bis das letzte COMMIT übergeben wird. Egal wie tief Ihre Verschachtelung ist, sie hat keine Auswirkung wenn das letzte COMMIT nicht übergeben wird.

Hier ist ein Beispiel für eine verschachtelte Transaktion:

USE pubs SELECT 'Before BEGIN TRAN',
TRANCOUNT  -- The value of 
TRANCOUNT is 0

BEGIN TRAN SELECT 'After BEGIN TRAN',
TRANCOUNT  -- The value of 
TRANCOUNT is 1

DELETE sales BEGIN TRAN nested SELECT 'After BEGIN TRAN nested',
TRANCOUNT
                   -- The value of 
TRANCOUNT is 2

DELETE titleauthor COMMIT TRAN nested Does nothing except decrement the value of
TRANCOUNT


    SELECT 'After COMMIT TRAN nested', 
TRANCOUNT
The value of
TRANCOUNT is 1

ROLLBACK TRAN

SELECT 'After ROLLBACK TRAN', 
TRANCOUNT The value of
TRANCOUNT is 0 
-- because ROLLBACK TRAN always rolls back all transactions and sets 
-- 
TRANCOUNT to 0.

SELECT TOP 5 au_id FROM titleauthor

In diesem Beispiel sehen wir, dass trotz des verschachtelten COMMIT TRAN der äußere ROLLBACK die Auswirkung der DELETE titleauthor rückgängig macht.

Hier ist ein weiteres Beispiel einer verschachtelten Transaktion:

USE pubs SELECT 'Before BEGIN TRAN',
TRANCOUNT  -- The value of 
TRANCOUNT is 0

BEGIN TRAN SELECT 'After BEGIN TRAN',
TRANCOUNT  -- The value of 
TRANCOUNT is 1

DELETE sales BEGIN TRAN nested SELECT 'After BEGIN TRAN nested',
TRANCOUNT
               -- The value of 
TRANCOUNT is 2

DELETE titleauthor ROLLBACK TRAN SELECT 'After COMMIT TRAN nested',
TRANCOUNT
    -- The value of 
TRANCOUNT is 0 because
ROLLBACK TRAN always rolls back all transactions and sets
TRANCOUNT 
    -- to 0.


IF (
TRANCOUNT > 0) BEGIN COMMIT TRAN Never makes it here cause of the ROLLBACK

SELECT 'After COMMIT TRAN',
TRANCOUNT
END

SELECT TOP 5 au_id FROM titleauthor
</code>
{br}
In diesem Beispiel erreicht die Ausführung niemals den '''COMMIT TRAN''' auf Grund der '''ROLLBACK TRAN''', sie macht alle Transaktionen rückgängig die zur Zeit ausgeführt werden und setzt den '''TRANCOUNT''' wieder auf '''0'''. Sofern '''ROLLBACK TRAN''' ohne Sicherungspunkt ausgeführt wird, wird '''ROLLBACK TRAN''' alle Transaktionen rückgängig machen und den '''TRANCOUNT''' wieder auf '''0''' setzen. Egal in welchem Zusammenhang sie aufgerufen wird.{br}
{br}
{TOP}
{br}
{br}
[anchor|#4]
==Save TRAN und Save Points==
Savepoints bieten einen Vorgang um Teile einer Transaktion rückgängig zu machen. Der Benutzer kann einen Savepoint oder eine Markierung in einer Transaktion setzen. Der Savepoint definiert einen Bereich zu der die Transaktion zurückkehren kann, wenn ein Abschnitt der Transaktion bedingungsweise abgebrochen wird. Der SQL Server bietet Ihnen die Möglichkeit einen Savepoint mit Hilfe der '''SAVE TRAN''' zu setzen, welche den Wert des '''TRANCOUNT''' nicht beeinflusst. Ein Rückschritt zu einem Savepoint (nicht einer Transaktion) beeinflusst den Wert der '''TRANCOUNT''' ebenfalls nicht. Allerdings muss das '''ROLLBACK''' explizit den Namen des Savepoints beinhalten, sonst wird die komplett Transaktion rückgängig gemacht.{br}
{br}
Das folgende Skript zeigt wie man Savepoints benutzt:{br}
{br}
<code sql>USE pubs
SELECT 'Before BEGIN TRAN main', 
TRANCOUNT
The value of
TRANCOUNT is 0


BEGIN TRAN main
    SELECT 'After BEGIN TRAN main', 
TRANCOUNT The value of
TRANCOUNT is 1

    DELETE sales
    SAVE TRAN sales  -- Mark a save point

    SELECT 'After SAVE TRAN sales', 
TRANCOUNT
The value of
TRANCOUNT is still 1


    BEGIN TRAN nested
        SELECT 'After BEGIN TRAN nested', 
TRANCOUNT The value of
TRANCOUNT is 2

        DELETE titleauthor
        SAVE TRAN titleauthor  -- Mark a save point

        SELECT 'After SAVE TRAN titleauthor', 
TRANCOUNT
The value of
TRANCOUNT is still 2

    ROLLBACK TRAN sales

    SELECT 'After ROLLBACK TRAN sales', 
TRANCOUNT The value of
TRANCOUNT is still 2


    SELECT TOP 5 au_id FROM titleauthor

IF (
TRANCOUNT > 0) BEGIN ROLLBACK TRAN SELECT 'AFTER ROLLBACK TRAN',
TRANCOUNT
    -- The value of 
TRANCOUNT is 0 because

ROLLBACK TRAN always rolls back all transactions and sets
TRANCOUNT 

    -- to 0.

END
    
SELECT TOP 5 au_id FROM titleauthor</code>{br}
{TOP}
{br}
{br}
[anchor|#5]
==Error Handling==
Die hier gezeigten Beispiele sind spezifisch für Stored Procedures, da sie die gewünschte Methode sind um mit einer Datenbank zu interagieren. Wird ein Fehler in einer Stored Procedure gefunden, ist das Beste was Sie machen können die sequentielle Ausführung des Codes zu stoppen und{br}
{br}
* entweder in ein anderes Code Segment der Prozedur zu springen (abzweigen)
* oder die Kontrolle wieder an die aufrufende Applikation zurückgeben.
{br}
Die automatische Variable '''ERROR''' wird benutzt um das Error Handling auszuführen. Sie beinhaltet die Fehler ID die von der letzten ausgeführten SQL Anweisung des Benutzers. Wenn eine Anweisung erfolgreich ausgeführt wird ist der Wert der '''ERROR''' Variable '''0'''. Um festzulegen ob eine Anweisung erfolgreich ausgeführt wurde wird eine '''IF''' Anweisung direkt nach der Ausführung des Statements ausgeführt um den Wert der '''ERROR''' Variable zu prüfen. Es ist unerlässlich die '''ERROR''' Variable nach der Ausführung eines Statements zu prüfen, weil der Wert nach der erfolgreichen Ausführung des nächsten Statements wieder auf '''0''' gesetzt wird. Tritt ein abfangbarer Fehler auf hat '''ERROR''' einen Wert größer '''0'''. Der SQL Server setzt den Wert nach jedem erfolgreichen Befehl wieder auf '''0''', d.h. sie müssen den Fehlerwert sofort erfassen. Meistens testen Sie die '''ERROR''' Variable auf Änderungen nach jeder '''INSERT''', '''UPDATE''' oder '''DELETE''' Anweisung.{br}
{br}
<code sql>CREATE PROCEDURE addTitle(@title_id VARCHAR(6), @au_id VARCHAR(11), 
                          @title VARCHAR(20), @title_type CHAR(12))
AS

BEGIN TRAN
    INSERT titles(title_id, title, type)
    VALUES (@title_id, @title, @title_type)

    IF (
ERROR <> 0) BEGIN PRINT 'Unexpected error occurred!' ROLLBACK TRAN RETURN 1 END

INSERT titleauthor(au_id, title_id) VALUES (@au_id, @title_id)

IF (
ERROR <> 0) BEGIN
        PRINT 'Unexpected error occurred!'
        ROLLBACK TRAN
        RETURN 1
    END

COMMIT TRAN

RETURN 0</code>
{br}
Diese Art der Lösung birgt beträchtige Wiederholung, gerade dann wenn in Ihrer Unternehmenslogik die Implementierung von mehr als zwei Transact-SQL benötigt wird. Eine elegantere Lösung ist es den Code in eine typische Bearbeitungsprozedur zu gruppieren:{br}
{br}
<code sql>CREATE PROCEDURE addTitle(@title_id VARCHAR(6), @au_id VARCHAR(11),
                          @title VARCHAR(20), @title_type CHAR(12))
AS

BEGIN TRAN
    INSERT titles(title_id, title, type)
    VALUES (@title_id, @title, @title_type)

    IF (
ERROR <> 0) GOTO ERR_HANDLER

INSERT titleauthor(au_id, title_id) VALUES (@au_id, @title_id)

IF (@@ERROR <> 0) GOTO ERR_HANDLER

COMMIT TRAN

RETURN 0

ERR_HANDLER: PRINT 'Unexpected error occurred!' ROLLBACK TRAN RETURN 1

Nach oben

ScrewTurn Wiki version 3.0.1.400. Some of the icons created by FamFamFam.