Datenbanken und mehr

15. März 2007

Wie speichere ich ein Datum in der DB?

Filed under: SQL Server — Urs Gehrig @ 23:54

Diese Frage wird mir immer wieder gestellt und meine Antwort darauf ist immer dieselbe: Natürlich in einem datetime Feld, ausser… Naja, eine Antwort wie man sie von einem Berater halt erwartet; einfach nie festlegen. Lass mich kurz das ausser erklären. Zuerst aber ein paar Worte zu Natürlich in einem datetime Feld.

Der SQL Server kennt zwei Datentypen für das Speichern von Datum und Uhrzeit:

Datentyp Wertebereich Genauigkeit
smalldatetime 1. Januar 1900 bis 6. Juni 2079 1 Minute
datetime 1. Januar 1753 bis 31. Dezember 9999 3.33 Millisekunden

Immer wieder werde ich gefragt „und was ist mit timestamp?“. Leider ist die Bezeichnung etwas irrtümlich ausgefallen; mit einer Zeitangabe hat timestamp absolut nichts zu tun. timestamp ist viel mehr eine Identity. Ein Identity Feld ist eindeutig innerhalb einer Tabelle und timestamp ist eindeutig innerhalb der ganzen Datenbank. Also nichts mit Zeit!

Leider existiert kein Datentyp für das separate Abspeichern eines Datums ohne Uhrzeit. Wenn dich aber trotzdem nur der Tag und nicht die Uhrzeit interessiert (z.B. für eine GROUP BY innerhalb eines Tages) so kannst du dies trotzdem einfach erreichen

GROUP BY DATEADD(day, DATEDIFF(day, ‚19000101‘, meinDatetimeFeld), ‚19000101‘)

Die Verwendung von datetime hat gegnüber varchar oder numeric eine Menge von Vorteilen. Bei allem was du in datetime speicherst bist du sicher, das dies auch Sinn macht; das Datum wird validiert. So kannst du z.B. nie den 29. Februar 2007 dort abspeichern, da 2007 kein Schaltjahr ist. Mit datetime kannst du auch rechnen. Mit Hilfe des Ausdruckes DATEADD(day, 14, GETDATE()) bekommst du z.B. das Datum in 14 Tagen oder mit DATEDIFF(week, deinGeburtstag, GETDATE()) erfährst du, wie viele Wochen alt du bist. Ist doch ganz einfach, oder?

Nun zum ausser…Falls du ein Geschichtsstudent bist und ein Verzeichnis aller Schlachten unserer Vorfahren im SQL Server ablegen willst, dann ist datetime ganz und gar nicht geeignet. Spätestens wenn du die Schlacht bei Morgarten erfassen willst, wirst du dein blaues Wunder erleben – der 15. November 1315 liegt weit ausserhalb des Gültigkeitsbereichs von datetime. Dass die Zeitrechnung im SQL Server erst im Jahre 1753 beginnt, hat mit der Umstellung vom julianischen zum gregorianischen Kalender zu tun. In England (und auch in den späteren USA) wurde der gregorianische Kalender in der Nacht vom 2. September auf den 14. September 1752 eingeführt. Upps, das muss ja eine tolle, lange Nacht gewesen sein! Leider nein, man hat lediglich 10 Tage übersprungen, um die Frühlings-Tagundnachtgleiche wieder mit dem 21. März in Übereinstimmung zu bringen. Falls du wirklich vor das Jahr 1753 gehen musst, bleibt dir leider nichts anderes übrig, als dein Datum als String oder Zahl in der DB abzulegen. Die Validierung und Rechenfunktionen musst du in diesem Falle aber selber implementieren. Kannst du aber mit dem Wertebereich und der gegebenen Genauigkeit leben, dann gibt es keinen Grund auf datetime respektive smalldatetime zu verzichten.

Beim Arbeiten mit datetime solltest du aber unbedingt auf ein paar Dinge achten. Notationen für Daten variieren von Land zu Land. Ob der SQL Server ein Datum z.B. als 15. März 2007 oder March 15. 2007 darstellt hängt in erster Linie von den Regions- und Sprachoptionen des Client ab, kann aber auch durch einen SET DATEFORMAT oder SET LANGUAGE Befehl übersteuert werden. Willst du das Datum unabhängig von irgendwelchen Einstellungen in einem fix definierten Format anzeigen, kannst du dieses vorgängig in einen String umwandeln

CONVERT(varchar, GETDATE(), 6) z.B. als: 15 Mar 07

Welche Formate unterstützt werden findest du im BOL unter CAST and CONVERT (Transact-SQL) .

Kritisch wird es bei einer T-SQL Abfrage der Art

SELECT * FROM Order WHERE OrderDate = ‚2007/11/03‘

Ist hier der 11. März oder der 3. November gemeint? In Abhängigkeit der diversen Einstellungen kann dies auf dem Entwicklungsserver der 11. März sein, während dem auf dem Produktivsystem das Datum als 3. November interpretiert wird. Um diesem Problem aus dem Weg zu gehen, unterstütz der SQL Server das Datumsformat nach ISO 8601, welches ein Datum mit Uhrzeit wie folgt codiert:

yyyy-mm-ddThh:mm:ss[.mmm] z.B. als: ‚2007-03-15T23:14:25.100′

Unabhängig von irgendwelchen Einstellungen und wenn und aber. Dies sollte also dein bevorzugtes Format für die Angabe eines Datums sein. Für nur einen Teil des vollständigen Datums gibt es alternativ auch noch

yyyymmdd z.B. als: ‚ 20070315‘
{ts ‚yyyy-mm-dd hh:mm:ss[.fff]‘}
z.B. als: {ts ‚2007-03-15 23:14:25‘}
{d ‚yyyy-mm-dd‘}
z.B. als: {d ‚2007-03-15‘}
{t ‚hh:mm:ss‘}
z.B. als: {t ’23:14:25′}

Kurz zusammengefasst: Benutze wann immer möglich datetime für das Ablegen eines Datums und verwende für die Notation von Konstanten die ISO 8601 Notation.

Advertisements

Schreibe einen Kommentar »

Es gibt noch keine Kommentare.

RSS feed for comments on this post. TrackBack URI

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

Erstelle eine kostenlose Website oder Blog – auf WordPress.com.

%d Bloggern gefällt das: