Richtiges Datum für SQL

15.12.2006 von Lorenz  Hölscher
Access mag sich einigermaßen landessprachlich geben, aber wenn es ans Eingemachte geht, muss es dann doch wieder Amerikanisch sein. Am häufigsten passiert dies beim Datum in einem SQL-Statement.

Listing 1 zeigt einen typischen Fall, wobei die Datumswerte normalerweise eher aus einem Eingabefenster kommen, was aber am Problem selber nichts ändert.

Sub LoescheAltdaten()
Dim datVon As Date
Dim datBis As Date
Dim strSQL As String
datVon = #12/24/2005#
datBis = Date - 14
strSQL = "DELETE * FROM [Bestellungen] WHERE " & _
"([Bestelldatum] >= " & _
datVon & " AND [Bestelldatum] <= " & datBis & ")"
MsgBox strSQL
'CurrentDb.Execute strSQL ' zu Testzwecken kommentiert
End Sub

Das Beispiel in Listing 1 ist doppelt fehlerhaft. Am leichtesten erkennbar sind noch die fehlenden #-Zeichen zur Kennzeichnung eines (länderspezifischen!) Datums innerhalb einer Zeichenkette.

Automatische Übersetzung

Wer es aber aus dem grafischen Abfrage-Editor von Access gewöhnt ist, dass darin ein deutsch formatiertes Datum steht, hat dort noch nie auf die tatsächliche SQL-Ansicht umgeschaltet. Die amerikanischen Funktionsnamen und Formate werden da nämlich kurzerhand ins Deutsche übersetzt.

Das hat nicht nur den Vorteil, dass Sie die aus VBA gewohnten Befehle wie Left() in Englisch eingeben können und sie nach Verlassen der Zelle sofort in Deutsch vorfinden. Es hat leider auch den Nachteil, dass Feldnamen wie Agent-No für eine Vertreter-Personalnummer zwar korrekt wegen des Minuszeichens in zwei vermutete Feldnamen zerlegt werden, aber dann das No fälschlich nochmals übersetzt wird. Nach der
Eingabe von Agent-No verwandelt der grafische Abfrage-Editor dies unbekümmert in [Agent]-[Nein].

SQL ohne Übersetzung

All das ist aber eine „Leistung“ des Access-Abfrage-Editors. Ein SQL-Befehl wie in Listing 1 wird jedoch bei CurrentDB.Execute ohne Kontakt mit der Access-Oberfläche direkt von der Jet-Engine ausgeführt.

Es ist daher sinnvoll, eine kleine Funktion zu schreiben, welche ein Datum im amerikanischen Format liefert. Listing 2 zeigt einen ersten Versuch. Die Doppelkreuze werden der Einfachheit halber dabei direkt mit angefügt.

Function SQLDatum(datQuelle As Date) As String
SQLDatum = "#" & Format(datQuelle, "MM/dd/yyyy") & "#"
End Function
Sub Test()
Const datTest = #3/5/2006#
MsgBox SQLDatum(datTest) & vbCrLf & _
"Monat: " & Month(datTest)
End Sub

Hoppla, haben Sie das mal getestet? Obwohl die Format-Anweisung scheinbar eindeutig aussieht, erhalten Sie keineswegs #05/03/2006# als Ergebnis, sondern #03.05.2006# mit Punkten dazwischen. Tatsächlich ist der Schrägstrich kein Literal, also das Zeichen selbst, sondern der Stell- vertreter für das Datumstrennzeichen aus der Systemsteuerung. Damit er ein Literal wird und wirklich als Schrägstrich erscheint, stellen Sie ihm einen Backslash voran, wie in Listing 3 zu sehen ist.

Function SQLDatum(datQuelle As Date) As String
SQLDatum = "#" & Format(datQuelle, "MM\/dd\/yyyy") & "#"
End Functi

Jetzt können Sie in allen SQL-Statements wie in Listing 4 jedes Datum mit dieser Funktion kapseln. Bei Bedarf lässt sich die Funktion auch so erweitern, dass die Uhrzeit mit angezeigt wird.

Sub LoescheAltdaten()
Dim datVon As Date
Dim datBis As Date
Dim strSQL As String
datVon = #12/24/2005#
datBis = Date - 14
strSQL = "DELETE * FROM [Bestellungen] WHERE " & _
([Bestelldatum] >= " & _
SQLDatum(datVon) & " AND [Bestelldatum] <= " & _
SQLDatum(datBis) & ")"
MsgBox strSQL
'CurrentDb.Execute strSQL
End Sub