Fehler-Behandlung und Protokollierung insbesondere von unvorhergesehenen Fehlersituationen in SQL-Routinen ist immens wichtig. Im ersten Artikel dieser Reihe wurde zunächst erklärt, wie Fehler in SQL-Routinen durch Condition Handler abgefangen werden können. In diesem Artikel wird nun anhand eines Beispiels gezeigt, wie die aufgetretenen Fehler in einer Log-Datei protokolliert werden können.

Für die Protokollierung von SQL-Fehlern und Warnungen werden alle Einzelteile, die im ersten Teil dieses Artikels besprochen wurden, zusammengesetzt. Im ersten Schritt wird eine Protokoll-Datei/Tabelle erstellt, in die die Fehler-Informationen ausgegeben werden.

Quelle: Birgitta Hauser

Bild 1. Erstellungsbefehl für die Protokoll-Datei ERRORLOG

Das Beispiel in Bild 1 zeigt das CREATE TABLE-Statement für die Tabelle ERRORLOG, in die in den weiteren Beispielen die Fehler und Warnungen ausgegeben werden. Die Spalten ErrSQLCODE, ErrSQLSTATE und MSGTEXT werden mit Informationen, die über das GET DIAGNOSTICS-Statement ermittelt werden können gefüllt.

Die Spalten ROUTINE, ROUTSCHEMA, SESSUSER, JOB und CHGDATTIM werden vom Datenbanken-Manager automatisch mit dem Inhalt aus Special Registers (Session_User, Current_Timestamp) oder Built-In-Globalen Variablen (Routine_Specific_Name, Routine_Schema, Job_Name) bestückt.

Anmerkung: Die Auditing-Spalten (Spalten, die mit GENERATE ALWAYS definiert wurden) können erst ab Release 7.3 verwendet werden. Die Spalten mit GENERATED ALWAYS … AS ROW CHANGE TIMESTAMP können jedoch bereits seit Release 6.1 definiert werden.

Stored Procedure mit Fehler-Protokollierung

Um die Fehler-Protokollierung in SQL-Routinen einzubinden, müssen entsprechende Condition Handler verwendet werden, über die ein bestimmter Status oder jeder beliebige Fehler behandelt wird. In diese Handler wird nun zusätzlich zur Fehler-Behandlung auch die die Protokollierung eingebunden.

Quelle: Birgitta Hauser

Stored Procedure mit Condition Handlern und Protokollierung

Das in Bild 2 gezeigt Beispiel zeigt die Syntax einer Stored Procedure, in der mehrere Condition Handler definiert wurden. Bei dem ersten Handler handelt es sich um einen Continue Handler, der den SQLSTATE 24501 (=Nicht geöffneter Cursor soll geschlossen werden) behandelt. Innerhalb des Handlers werden zunächst die lokalen Variablen LocMsgText, LocSQLCODE und LocSQLSTATE definiert.

Die Werte mit denen diese Variablen versorgt werden, werden über das GET DIAGNOSTICS-Statement ermittelt. Das Schlüssel-Wort MESSAGE_TEXT liefert den Nachrichten-Text, das Schlüssel-Wort DB2_RETURNED_SQLCODE liefert den SQLCODE und RETURNED_SQLSTATE den SQLSTATE des vorherigen Statements.

Die ermittelten und in Hostvariablen übertragene Werte werden im Anschluss mit einem INSERT-Statement in die Protokoll-Datei ERRORLOG geschrieben. Der Insert-Befehl wird explizit nicht unter Commit (with NC = No Commit) ausgeführt, damit auch beim Zurücksetzen über Rollback die Fehlersituation dokumentiert bleibt.

Die anderen Informationen, wie der aktuelle Benutzer oder der qualifizierte Job werden automatisch durch den Datenbanken-Manager ermittelt und in dem Datensatz aktualisiert, da die entsprechenden Spalten als Auditing-Spalten definiert wurden. Um die Warnungen zu protokollieren, wurde ein weiterer Continue Handler angelegt, der für jede Warnung (SQLWARNING) aktiviert wird.

Quelle: Birgitta Hauser

Inhalt der Protokoll-Datei ERRORLOG

Alle anderen SQL-Fehler (SQLEXCEPTION) werden über einen Exit-Handler abgefangen. Nach Abarbeitung des Handlers bzw. nach der Protokollierung wird die SQL-Routine (ohne Rollback) verlassen.

Der SQL-Code in den Handlern für die Warnungen (SQLWARNING) und nicht behandelten Fehler (SQLEXCEPTION) entspricht dem Source-Code des Handlers für den SQLSTATE 24501. Aus diesem Grund wurden in den SQL-Code entsprechende Kommentare eingefügt.

Das Bild 3 zeigt den Inhalt der Protokoll-Datei ERRORLOG, nachdem die Stored Procedure mehrfach in unterschiedlichen Jobs, in denen unterschiedliche Fehler provoziert wurden, ausgeführt wurde.

SQL Include Statement – SQL Copy-Strecke

In dem Stored Procedure-Beispiel wurde der gleiche Source Code in mehreren Handlern benötigt. Den gleichen Source-Code mehrfach zu wiederholen bedeutet nicht nur ein schlechtes Design, sondern ist zudem noch fehleranfällig.

Mit dem ersten Technology Refresh in Release 7.3 wurde das SQL-Statement INCLUDE für die SQL-Programmierung eingeführt. Mit Hilfe des INCLUDE-Statements können gesicherte Code-Schnipsel den Source Code eingebunden werden, genau wie Copy-Strecken in RPG oder CL. Die Einbindung muss syntaktisch korrekt sein, d.h. Variablen Definitionen oder Cursor Deklarationen dürfen nicht in den auszuführenden Source-Code eingemischt werden und umgekehrt.

Der einzubindende Source Code kann entweder in einer klassischen Quellen-Teildatei oder in einer IFS-Datei hinterlegt werden. Bei dem Source Code kann es sich um reine SQL-Statements oder C-Code handeln.

Detaillierte Informationen über das erweiterte INCLUDE-Statement können auf IBMs Developerworks-Site gefunden werden.

Um unsere Stored Procedure zu vereinfachen und um die Protokollierung an allen Stellen, an denen sie erforderlich ist einbinden zu können, wurde der SQL-Code für den Condition Handler in der Teildatei CPYERRLOG in der Quellen-Datei QSQLCPY hinterlegt.

BEGIN und END wurden nicht in die Copy-Strecke übernommen. Auf diese Weise können in den Handlern noch zusätzliche Variablen definiert und auch weitere auszuführende SQL-Statements in dem gleichen Compound-Statements hinterlegt werden.

Quelle: Birgitta Hauser

Copy-Strecke CPYERRLOG

Das Beispiel in Bild 4 zeigt den Inhalt der Copy-Strecke CPYERRLOG.

Diese Copy-Strecke kann nun an allen Stellen, an denen eine Fehler-Protokollierung erwünscht ist mit Hilfe des INCLUDE-Statements eingebunden werden.

Das Beispiel in Bild 5 zeigt den vereinfachten Quell-Code der Stored Procedure aus den vorherigen Beispielen. Die Fehler-Protokollierung ist in allen Handler als Copy-Strecke eingebunden.

Quelle: Birgitta Hauser

Stored Procedure mit eingebundenen Copy-Strecken

Die Protokollierung ist für die Nachverfolgung und Fehlerbehandlung immens wichtig. Mit Hilfe von Auditing Spalten und dem SQL INCLUDE-Statements können solche Protokollierungen leicht in jede beliebige SQL-Routine eingebunden werden.

Birgitta Hauser

Midrange Techknowletter