Debuggen von SQL-SELECT-Anweisungen

15.02.2006 von Helma  Spona
In größeren Anwendungen ist es oft hilfreich, wenn der Benutzer mit SQL-Kenntnissen eigene Abfragen erstellen kann, ohne dass Sie ihm den Abfrageassistenten zur Verfügung stellen. Allerdings sollte dann auf andere Weise gewährleistet sein, dass der SQL-Code korrekt ist. Wie das geht, zeigt folgender Beitrag

Benutzer mit grundlegenden SQL-Kenntnissen können im Prinzip ganz einfach durch Eingabe der SQL-Anweisungen und eines Namens eigene Abfragen und Filter erstellen. Dazu müssen sie nur die SQL Anweisung unter dem eingegebenen Namen als Abfrage speichern. Problematisch ist das jedoch, wenn die SQL-Anweisung fehlerhaft formuliert wurde. Zum einen ist dann nicht immer das Speichern möglich, zum anderen verursacht eine solche Abfrage spätestens dann Fehler, wenn sie ausgeführt werden soll. Um das zu vermeiden, sollten Sie vorab prüfen, ob die SQL-Anweisung korrekt ist.

Trial and Error

Zur Syntaxprüfung einer SQL-Anweisung können Sie einmal versuchen, die Anweisung mit der Execute-Methode des Connection-Objekts auszuführen. Problematisch ist dies natürlich bei Aktionsabfragen. Wenn zur Prüfung schon Datensätze gelöscht werden, die zu diesem Zeitpunkt vielleicht noch benötigt werden, ist das natürlich nicht praktikabel. Aus diesem Grund müssen Sie dafür sorgen, dass ausschließlich Auswahlabfragen, die mit dem Schlüsselwort SELECT beginnen, überprüft werden. Andernfalls sollten Sie eine entsprechende Fehlermeldung zurückgeben. Wie das geht, zeigt Listing 1.

Function SyntaxCheck(strSQL As String, _
objConn As ADODB.Connection, Optional ByRef _
strFehler As String) As Boolean
'Prüfen, ob es sich um eine SELECT-Anweisung handelt
If Not (InStr(1, Trim(strSQL), "SELECT") = 1) Then
'Keine Select-Anweisung
strFehler = "Es handelt sich nicht um eine " & _
"SELECT-Anweisung, ein Test ist daher nicht möglich!"
SyntaxCheck = False
Exit Function
End If
On Error GoTo FEHLER
objConn.Execute (strSQL)
SyntaxCheck = True
Exit Function
FEHLER:
strFehler = Err.Description
SyntaxCheck = False
Exit Function
End Function

Die Funktion SyntaxCheck erwartet zwei Parameter. Der dritte ist optional. Mit dem ersten geben Sie die zu prüfende SQL-Anweisung an, mit dem zweiten Parameter die Datenbankverbindung, die zur Prüfung verwendet werden soll. Der dritte Parameter ermöglicht die Übergabe einer Variablen des Typs String, über die zusätzlich zum booleschen Rückgabewert die Fehlerbeschreibung zurückgegeben werden kann.

Innerhalb der Funktion prüfen Sie zunächst, ob die SQL-Anweisung mit SELECT beginnt. Dazu schneiden Sie mit Trim die führenden und abschließenden Leerzeichen ab und prüfen dann mit der instr-Funktion, ob die Zeichenkette mit SELECT beginnt. Falls das nicht der Fall ist, definieren Sie als Rückgabewert false und weisen dem Parameter strFehler eine entsprechende Fehlermeldung zu.

Mit der Anweisung On Error GoTO FEHLER schalten Sie dann die Standardfehlerbehandlung aus und sorgen dafür, dass bei einem Laufzeitfehler zur Marke FEHLER gesprungen wird. Hier weisen Sie der Variablen strFehler die Fehlerbeschreibung des Err-Objekts zu und legen den Rückgabewert der Funktion auf false fest. Mit der Execute-Methode führen Sie dann die SELECTAnweisung aus. Gelingt dies, wird die Anweisung SyntaxCheck=True ausgeführt und der Rückgabewert auf True gesetzt. Andernfalls wird in die Fehlerbehandlungsroutine FEHLER verzweigt. In beiden Fällen wird die Funktion nun mit Exit Sub verlassen.

Ein Formular zur Abfrageerstellung

Um dem Benutzer die Eingabe und Speicherung von SQL-Abfragen zu ermöglichen, benötigen Sie ein Formular (Bild 1), das mindestens über folgende Steuerelemente verfügt:

Bild 1: Aufbau des Formulars.

Für die Schaltfläche bttSpeichern setzen Sie die Eigenschaft Aktiviert auf Nein, damit Sie die Schaltfläche erst dann freigeben können, wenn eine korrekte SQL-Anweisung eingegeben wurde.

Nun müssen Sie noch für beide Schaltflächen je eine Ereignisprozedur für das Click-Ereignis erstellen und für das Textfeld txtSQL eine Ereignisprozedur für das Change-Ereignis. Diese Prozeduren füllen Sie mit dem in Listing 2 gezeigten Code. Die Ereignisprozedur für das Change-Ereignis stellt sicher, dass der Speichern-Button wieder deaktiviert wird, wenn der Benutzer nach der Prüfung der SQL-Anweisungen Änderungen im Feld vornimmt. Er könnte sonst nachträglich eine korrekte SQL-Anweisung verändern und doch wieder Fehler einbauen, die dann mit gespeichert würden.

Private Sub bttPruefen_Click()
Dim strFehler As String
Dim boolErg As Boolean
strFehler = ""
boolErg = SyntaxCheck(Me.txtSQL.Value, _
Application.CurrentProject.Connection, _
strFehler)
If boolErg = False Then
Me.txtErgebnis.Value = "FEHLER: " & strFehler
Me.bttSpeichern.Enabled = False
Else
Me.bttSpeichern.Enabled = True
Me.txtErgebnis.Value = "OK!"
End If
End Sub
Private Sub bttSpeichern_Click()
'Speichert die SQL-Anweisung als Abfrage
Dim objQD As QueryDef
Dim strName As String
strName = InputBox("Bitte geben Sie den Namen ein, " & _
"unter dem die Abfrage gespeichert werden soll: ", _
"Abfragename")
On Error GoTo FEHLER
'Abfrage speichern
Set objQD = Application.CurrentDb.CreateQueryDef( _
strName, Me.txtSQL.Value)
Me.txtErgebnis.Value = "Abfrage " & strName & " gespeichert!"
Exit Sub
FEHLER:
Me.txtErgebnis.Value = "FEHLER: Die Abfrage konnte " & _
"nicht gespeichert werden" & _
", folgender Fehler trat auf: " & _
vbCrLf & Err.Description
Exit Sub
End Sub
Private Sub txtSQL_Change()
Me.bttSpeichern.Enabled = False
End Sub

Die SQL-Anweisung prüfen

Klickt der Benutzer auf die Schaltfläche Prüfen, soll die SQL-Anweisung geprüft werden. Dazu wird in der Ereignisprozedur bttPruefen_Click die Funktion SyntaxCheck aufgerufen.

Als Erstes müssen Sie dazu eine Variable des Typs String definieren und ihr eine leere Zeichenfolge als Wert zuweisen. Diese Variable, hier strFehler, dient zur Rückgabe der Fehlermeldung. Anschließend rufen Sie die Funktion Syntax- Check auf. Ihr übergeben Sie den Wert des Textfeldes txtSQL und den Wert der Connection-Eigenschaft der aktuellen Datenbank sowie zuletzt die Variable strFehler.

Gibt die Funktion False zurück, geben Sie den Inhalt der Variablen strFehler in das Textfeld txtErgebnis aus und deaktivieren den Speichern- Button. Andernfalls aktivieren Sie den Speichern- Button und geben als Ergebnis OK aus.

Die Abfrage erstellen

Bei korrekter SQL-Anweisung soll diese als Abfrage gespeichert werden können. Zum Speichern ist ein Name erforderlich, der hier zunächst über die Funktion InputBox abgefragt und dann als erster Parameter an die Methode CreateQueryDef übergeben wird. Den zweiten Parameter bildet die SQL-Anweisung für die Abfrage. Falls es dabei zu einem Fehler kommt, wird ab der Sprungmarke FEHLER die Fehlermeldung ausgegeben und die Prozedur verlassen. Tritt kein Fehler auf, wird eine Bestätigungsmeldung ausgegeben, dass die Abfrage gespeichert wurde.