By Frank Kalis
Was tun, wenn man den Tag, den Monat und das Jahr fein säuberlich in Einzelteilen zerlegt hat? Schauen wir uns mal verschiedene Methoden an, daraus ein gültiges Datum herzustellen.
Vor einigen Tagen schrieb jemand in der deutschen SQL Server Newsgroup über ein Problem beim Zusammensetzen von Einzelteilen zu einem gültigen Datum. Dies nehme ich zum Anlass, mir mal meine Gedanken zu diesem Problem zu machen. :-) Also, gegeben sind folgende Daten:
DECLARE @Tag INT DECLARE @Monat INT DECLARE @Jahr INT SELECT @Tag = DAY(GETDATE()) , @Monat = MONTH(GETDATE()) , @JAHR = YEAR(GETDATE())
Ein wichtiger Hinweis noch vorweg. Keine der gezeigten Methoden hier wird auf ein Schaltjahr überprüfen! Dies bleibt dem geneigten Leser überlassen. Hinweis: SQL Server bietet dafür die nützliche Funktion ISDATE() an. :-)
Methode 1:
SELECT CAST(@Tag + '.' + @Monat + '.' + @Jahr AS DATETIME) Server: Msg 245, Level 16, State 1, Line 10 Syntax error converting the varchar value '.' to a column of data type int.
Oops, da haben wir die vielleicht naheliegenste Alternative einsetzen wollen und dabei glatt die Regeln zur Rangfolge der Datentypen übersehen. Also, schnell das Skript abändern.
SELECT CAST( CAST(@Tag AS VARCHAR(2)) + '.' + CAST(@Monat AS VARCHAR(2)) + '.' + CAST(@Jahr AS CHAR(4)) AS DATETIME) ------------------------------------------------------ 2005-11-02 00:00:00.000 (1 row(s) affected)
Methode 2: Die Vorsichtigen möchten vielleicht von vornherein etwaige Problem mit der Datumskonvertierung vermeiden, und bevorzugen das ISO Format JJJJMMTT.
SELECT CAST( CAST(@Jahr AS CHAR(4)) + CAST(@Monat AS VARCHAR(2)) + CAST(@Tag AS VARCHAR(2)) AS DATETIME) Server: Msg 241, Level 16, State 1, Line 17 Syntax error converting datetime from character string.
Hoppla, was soll das denn jetzt? Nun, ganz einfach. Wir befinden uns im Monat Februar. Konvertiert man diesen in einen Integer Wert erhält man eine 2. Setzt man nun die Einzelteile zusammen, erhält man:
SELECT CAST(@Jahr AS CHAR(4)) + CAST(@Monat AS VARCHAR(2)) + CAST(@Tag AS VARCHAR(2)) -------- 2005211 (1 row(s) affected)
und diesen Wert kann SQL Server nicht in ein gültiges Datum umwandeln. Gleiches gilt auch für die ersten neun Tage jedes Monats. Also, einen generischen Workaround einbauen:
SELECT CAST( CAST(@Jahr AS CHAR(4)) + REPLACE(STR(@Monat,2),' ',0) + REPLACE(STR(@Tag,2),' ',0) AS DATETIME) ------------------------------------------------------ 2005-02-11 00:00:00.000 (1 row(s) affected)
So, nun ist es egal, ob der Tag (Monat) ein oder zwei Zeichen besitzt. Besitzt er nur ein Zeichen, stellt die STR() Funktion automatisch ein Leerzeichen an den Anfang, welches durch REPLACE() ersetzt wird. Enthält der Tag (Monat) hingegen zwei Zeichen, braucht nicht an den Anfang gestellt und ersetzt werden. Jetzt hat man sich ein sicheres Datum gebaut, welches auf keine Fehler laufen sollte.
Methode 3: Tja, aller guten Dinge sind drei. Und diese Variante ist mein persönlicher Favorit, da man hier die wenigsten Tastaturanschläge braucht. :-)
SELECT CAST( STR(@Jahr*10000+@Monat*100+@Tag) AS DATETIME) ------------------------------------------------------ 2005-02-11 00:00:00.000 (1 row(s) affected)