Womit kann man jeden Programmierer zum
Weinen bringen? Richtig: wenn es ums Datum geht. In SQL ist das aber gar nicht
so dramatisch und sicher nichts, wovor man Angst haben muss. Wir sehen uns in
diesem Beitrag an, wie man in SQL mit Datumsfunktionen arbeiten, das Datum im
gewünschten Format ausgeben und welche Datentypen man dafür verwenden kann.
Die gebräuchlichsten Datumsfunktionen in SQL
Mit diesen Funktionen kommt man schon
ziemlich weit. Wer sich damit noch nicht zufrieden geben will: Eine
Komplettübersicht über alle Datumsfunktionen findet Ihr in der Microsoft-Dokumentation.
SYSDATETIME() und GETDATE() – aktuelles Datum und Uhrzeit
Mit SYSDATETIME()
und GETDATE() könnt Ihr das aktuelle
Datum abfragen; dabei ist GETDATE() auf
mehrere Millisekunden und SYSDATETIME() auf
Nanosekunden genau. Ein weiterer nicht unerheblicher Unterschied ist der
verbrauchte Speicherplatz; SYSDATETIME() verbraucht
dabei 6-8 Bytes (entsprechend weniger, wenn die Millisekunden oder gar die Zeit
gar nicht benötigt wird), GETDATE() braucht
8 Bytes.
Wer jetzt meint, Speicherplatz ist
billig und auf das bisschen kommt es wohl auch nicht an: die Menge machts. Bei
potenziell Millionen von Einträgen kann die konsequente Verwendung von
optimalen Datentypen sehr wohl einen Unterschied machen. Aber das ist ein
anderes Thema.
DAY(), MONTH(), YEAR() und DATEPART() – Datumsanteile abfragen
Mit DAY(),
MONTH() oder YEAR()
kann man sich den entsprechenden Datumsanteil als Integer ausgeben
lassen; ebenso mit DATEPART(). Bei letzterem
muss allerdings noch spezifiziert werden, welchen Datumsanteil man denn gerne
hätte, und abhängig vom Datentyp des verwendeten Datums lassen sich bis zu
Nanosekunden ausgeben.
DATEPART(day,
date),
DATEPART(month,
date) oder
DATEPART(year,
date) führen
zum exakt gleichen Ergebnis wie DAY(date),
MONTH(date) oder YEAR(date).
DATENAME() – Wochentag oder Monatsname
Mit DATENAME()
kann man sich den Namen eines Wochentages oder den Monatsnamen ausgeben
lassen. Für andere Ausgaben macht DATENAME() nicht
viel Sinn, da wir für alle anderen wieder Zahlen herausbekommen.
DATEADD() – Daten addieren
Mit DATEADD()
kann man eine Zeitspanne zum angegebenen Datum hinzuaddieren. Wird eine
negative Zahl eingegeben, wird diese Zeitspanne vom angegebenen Datum
abgezogen.
DATEDIFF() – Differenz zwischen zwei Daten
Mit DATEDIFF()
kann man eine Datumsdifferenz zwischen zwei Daten ermitteln. Abhängig
von der Abfrage bekommt man einen Integer-Wert zurück, der für die Differenz in
der angegebenen Größenordnung (Jahre, Tage, …) steht. Liegt das Enddatum vor
dem Startdatum, ist der Ausgabewert negativ.
Datepart Parameter – was wollen
wir abfragen?
Damit DATEPART(),
DATEADD() und DATEDIFF()
funktionieren, müssen wir genau angeben, welchen Datumsteil (datepart) wir abfragen wollen.
Die folgende Tabelle zeigt die
wichtigsten Intervalle, die für die Datumsabfragen verwendet werden können.
Leider gibt es dazu ein paar
Abweichungen, wenn wir das Datum individueller formatieren wollen; dazu kommen
wir noch im Abschnitt „Format“.
Die vollständige Liste der datepart- Angaben findet Ihr in der
Microsoft-Dokumentation.
FORMAT() – wie soll etwas ausgegeben werden?
Das Problem mit dem Datum, das die
bereits erwähnten Verzweiflungsausbrüche bei Programmierern auslöst, sind die
vielen unterschiedlichen Formate, in denen das Datum in unterschiedlichen
Regionen der Welt dargestellt wird.
Da gibt es YYYY-DD-MM, YYYY-MM-DD,
YYYY/MM/DD, DD.MM.YYYY und noch eine ganze Reihe anderer Varianten. Meistens
wird die Formatierung des Datums, das aus der Datenbank kommt, clientseitig
oder in einem Zwischenschritt, beispielsweise mit C# erledigt. Wenn es aber
unbedingt serverseitig passieren soll, haben wir mehrere Möglichkeiten.
Die SQL Server Funktion FORMAT() erlaubt uns, sehr individuelle
Formatierungen durchzuführen. FORMAT() funktioniert
unter anderem mit den Datentypen int,
float, money – und eben auch mit Datumsformaten (date, time, datetime, datetime2). Der Datentyp des zurückgegebenen Wertes bei FORMAT() ist nvarchar
(oder NULL).
Für einen vollständigen Überblick über alle
akzeptierten Datentypen könnt Ihr einen Blick in die Microsoft-Dokumentation
werfen.
Die einfachste
Variante sieht so aus:
FORMAT() und Datum
Wir geben
einen Wert ein, der in ein bestimmtes Format gebracht werden soll, gefolgt vom
gewünschten Format. Das geht auch mit Datum…
…allerdings
müssen wir das Datum irgendwo auslesen, entweder aus einer Datumsfunktion oder
aus einer Tabellenspalte, die ein Datum enthält; die Angabe eines einzelnen
konkreten Datums würde hier nicht funktionieren, da dies als Text (varchar) interpretiert wird.
In der
Praxis arbeiten wir aber normalerweise ohnehin mit Daten, die aus einer Tabelle
oder einer Datumsfunktion kommen, und nicht mit einzelnen, händisch
eingegebenen Daten.
FORMAT() und Variablen
Für die
Anwendung von FORMAT()
ist auch die Verwendung von Variablen hervorragend geeignet:
Über eine
Variable könnte theoretisch auch wieder ein konkretes Datum angegeben werden,
da ja hier auch ein Datentyp definiert wird (nicht empfehlenswert):
FORMAT() und der culture-Parameter
Optional kann
noch ein weiterer Parameter (culture)
eingegeben werden, mit dem sich eine regionsbezogene Formatierung erreichen
lässt:
Das kleine 'd' im format-Parameter
bedeutet, dass das Datum in Zahlen ausgegeben wird; bei großem 'D' würde der Monat und (je nach regionaler
Konvention) auch der Wochentag ausgeschrieben werden, z.B.:
Eine
vollständige Übersicht über unterstützte culture-Codes
gibt es in der Microsoft-Dokumentation. (Diese
Übersicht ist derzeit nur auf Englisch verfügbar, aber die Tabelle ist
selbsterklärend.)
Da in vielen
Regionen die gleichen Formate für die Datumsanzeige verwendet werden, macht es
keinen Sinn, sämtliche verfügbaren culture-Codes anzugeben. Im Gegenteil, das
wäre eine massive unnötige Belastung für die Abfrage.
Wer es noch
genauer wissen möchte: Die Microsoft-Dokumentation zum Thema FORMAT() findet
Ihr hier.
CONVERT() und CAST() – umwandeln von Datentypen
Mit CONVERT() und CAST() ist
es möglich, einen Datentyp in einen anderen zu verwandeln.
Wir sehen
uns hier allerdings nur die Fälle an, die für unser Thema „Datum“ relevant
sind.
Mit beiden
Anweisungen lässt sich ein Datentyp in einen anderen konvertieren; allerdings
ist die Syntax bei CONVERT() und CAST() ein wenig anders und CONVERT() bietet noch die zusätzliche Option von
sogenannten Styles.
CAST() und Datum
Wollen wir
mittels CAST() ein Datum als Text (also etwa
als varchar oder nvarchar) darstellen (oder umgekehrt), sieht das so aus:
Es ist
möglich, mittels CAST() einen Datumswert als
Text darzustellen oder umgekehrt. Mit CAST() allein
haben wir allerdings keinen Einfluss darauf, wie unser Datum nun dargestellt
wird. Geben wir eine Länge (length) an, beispielsweise varchar(20), müssen wir außerdem noch darauf achten, dass sich das,
was wir darstellen wollen, in dieser Anzahl an Zeichen überhaupt ausgeht.
Der
umgekehrte Weg, Text in ein Datum umzuwandeln, wäre nicht empfehlenswert
(obwohl es theoretisch möglich ist), denn hier haben wir das Problem, dass wir
nicht sicher sein können, welcher Wert als Tag oder Monat interpretiert wird.
Glücklicherweise kommt dieser Fall in der Praxis so gut wie nicht vor, da wir
ja normalerweise Werte aus einer Tabelle auslesen und nicht einzelne Daten
händisch eingeben.
CONVERT() und Datum
Auch CONVERT() konvertiert einen Datentyp in einen
anderen, wie der Name schon sagt, allerdings haben wir hier noch die
Möglichkeit, einen sogenannten Style
anzugeben, der zugleich auch für ein bestimmtes Format sorgt.
CONVERT(), Datum und der Style-Parameter
Den Style
geben wir über eine Zahl ein. Liegt diese Zahl über 100, wird das Jahrhundert
mit angegeben (yyyy), sonst nur die Jahreszahl (yy). Damit das nicht zu einfach
wird, gibt es natürlich auch hier ein paar Ausnahmen.
In der
folgenden Tabelle seht Ihr einen Überblick über einige gebräuchliche Standards
und die dazugehörigen Style-Angaben.
Einen
vollständigen Überblick über alle Standards findet Ihr wieder in der
Microsoft-Dokumentation.
Mit all
diesem Wissen ausgerüstet sollte es Euch jetzt leichter fallen, Eure
Datumsangaben in das von Euch gewünschte Format zu bringen.
Viel Spaß
beim Ausprobieren, und vielleicht sehen wir uns ja in einem unserer Kurse zum Thema SQL!