Dieser Artikel befasst sich mit den Hauptunterschieden zwischen datetime2 und datetimeoffset Datentypen in SQL Server.
Beide Datentypen werden zum Speichern von Datums- und Uhrzeitwerten verwendet. Beide sind sehr ähnlich, aber mit einem entscheidenden Unterschied; der datetimeoffset speichert den Zeitzonenoffset.
Dies führt auch zu datetimeoffset verwendet mehr Speicherplatz als datetime2 , also würden Sie nur datetimeoffset verwenden wenn Sie den Zeitzonen-Offset benötigen.
Hier ist eine Tabelle, die die Hauptunterschiede zwischen diesen beiden Typen umreißt.
Funktion | datetimeoffset | datetime2 |
---|---|---|
SQL-konform (ANSI &ISO 8601) | Ja | Ja |
Zeitraum | 0001-01-01 bis 9999-12-31 | 0001-01-01 bis 9999-12-31 |
Zeitbereich | 00:00:00 bis 23:59:59.9999999 | 00:00:00 bis 23:59:59.9999999 |
Zeichenlänge | mindestens 26 Positionen höchstens 34 | mindestens 19 Positionen maximal 27 |
Speichergröße | 8 bis 10 Bytes, je nach Genauigkeit* * Plus 1 Byte zum Speichern der Genauigkeit | 6 bis 8 Byte, je nach Genauigkeit* * Plus 1 Byte zum Speichern der Genauigkeit |
Genauigkeit | 100 Nanosekunden | 100 Nanosekunden |
Präzision auf Sekundenbruchteile | Ja | Ja |
Benutzerdefinierte Genauigkeit für Sekundenbruchteile | Ja | Ja |
Zeitzonenverschiebungsbereich | -14:00 bis +14:00 | Keine |
Bewusstsein und Erhaltung der Zeitzonenverschiebung | Ja | Nein |
Sommerzeit bewusst | Nein | Nein |
Soll ich „datetime2“ oder „datetimeoffset“ verwenden?
Dies hängt davon ab, ob Sie einen Zeitzonenoffset einbeziehen müssen oder nicht.
Wenn Sie einen Zeitzonen-Offset einschließen müssen, müssen Sie datetimeoffset verwenden .
Wenn nicht, verwenden Sie datetime2 , da Sie Speicherplatz sparen und potenzielle Probleme mit einem (möglicherweise falschen) Zeitzonenoffset in Ihren Daten beseitigen.
Beispiel 1 – Grundlegender Vergleich
Hier ist ein kurzes Beispiel, um den grundlegenden Unterschied zwischen datetime2 zu demonstrieren und datetimeoffset .
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime2 datetime2(7); SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime2 = @thedatetimeoffset; SELECT @thedatetimeoffset AS 'datetimeoffset', @thedatetime2 AS 'datetime2';
Ergebnis:
+------------------------------------+-----------------------------+ | datetimeoffset | datetime2 | |------------------------------------+-----------------------------| | 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.5555555 | +------------------------------------+-----------------------------+
Hier setze ich ein datetime2 Variable auf den gleichen Wert wie datetimeoffset Variable. Dadurch wird der Wert in datetime2 konvertiert und wir können dann ein SELECT
verwenden -Anweisung, um den Wert jeder Variablen anzuzeigen.
Beide Variablen verwenden eine Skala von 7, was bedeutet, dass sie 7 Dezimalstellen haben.
In diesem Fall besteht der einzige Unterschied zwischen den beiden darin, dass der datetimeoffset Der Wert enthält den Zeitzonenoffset und datetime2 Wert nicht.
Beispiel 2 – Ändern der Genauigkeit
Bei beiden Typen können Sie eine Genauigkeit angeben (indem Sie eine Skala zwischen 0 und 7 verwenden). Daher ist es möglich, datetime2 festzulegen Wert auf eine niedrigere Genauigkeit als datetimeoffset Wert (und umgekehrt).
Beispiel:
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime2 datetime2(3); SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime2 = @thedatetimeoffset; SELECT @thedatetimeoffset AS 'datetimeoffset', @thedatetime2 AS 'datetime2';
Ergebnis:
+------------------------------------+-------------------------+ | datetimeoffset | datetime2 | |------------------------------------+-------------------------| | 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.556 | +------------------------------------+-------------------------+
Hier setze ich das datetime2 Wert auf eine Skala von 3, was bedeutet, dass er am Ende 3 Dezimalstellen statt 7 hat. In diesem Fall werden seine Sekundenbruchteile aufgerundet (weil die nächste Nachkommastelle 5 oder höher ist).
Wir können also sehen, dass es möglich ist, einen anderen Datums-/Uhrzeitwert zu erhalten, abhängig von den Bruchteilen von Sekunden, die wir datetime2 zuweisen . Dies funktioniert auch in die andere Richtung (z. B. wenn wir von datetime2(7) konvertieren zu datetimeoffset(3) ).
Wenn wir jedoch den Bruchteil reduzieren, wird keine Rundung durchgeführt:
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime2 datetime2(3); SET @thedatetimeoffset = '2025-05-21 10:15:30.5554444 +07:30'; SET @thedatetime2 = @thedatetimeoffset; SELECT @thedatetimeoffset AS 'datetimeoffset', @thedatetime2 AS 'datetime2';
Ergebnis:
+------------------------------------+-------------------------+ | datetimeoffset | datetime2 | |------------------------------------+-------------------------| | 2025-05-21 10:15:30.5554444 +07:30 | 2025-05-21 10:15:30.555 | +------------------------------------+-------------------------+
Beispiel 3 – Setzen von Werten aus String-Literalen
In den vorherigen Beispielen wurde datetime2 value wurde zugewiesen, indem er auf den gleichen Wert wie datetimeoffset gesetzt wurde Wert. Wenn wir das tun, führt SQL Server eine implizite Konvertierung durch, damit die Daten dem neuen Datentyp „passen“.
Wir können den gleichen Wert auch direkt datetime2 zuweisen Variable (auch wenn die offizielle Dokumentation nicht explizit angibt, dass sie ein String-Literal mit einem Zeitzonen-Offset akzeptiert):
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime2 datetime2(7); SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime2 = '2025-05-21 10:15:30.5555555 +07:30'; SELECT @thedatetimeoffset AS 'datetimeoffset', @thedatetime2 AS 'datetime2';
Ergebnis:
+------------------------------------+-----------------------------+ | datetimeoffset | datetime2 | |------------------------------------+-----------------------------| | 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.5555555 | +------------------------------------+-----------------------------+
Beispiel 4 – Speichergröße
Die datetime2 Der Datentyp benötigt zwei Bytes weniger Speicherplatz als datetimeoffset für jede gegebene Genauigkeit.
Die datetime2 kann je nach Genauigkeit entweder 6, 7 oder 8 Byte groß sein.
Der datetimeoffset kann je nach Genauigkeit entweder 8, 9 oder 10 Byte groß sein.
Microsoft gibt an, dass die datetime2 type verwendet auch 1 zusätzliches Byte, um seine Genauigkeit zu speichern, in diesem Fall würde es mindestens 3 Bytes mehr als smalldatetime verwenden .
Dies gilt auch für datetimeoffset (auch wenn es nicht ausdrücklich in der Microsoft-Dokumentation angegeben ist).
Das hängt jedoch davon ab, ob wir es in einer Tabelle oder in einer Variablen speichern und ob wir es in eine binäre Konstante konvertieren oder nicht.
Folgendes passiert, wenn wir DATALENGTH()
verwenden Funktion, um die Anzahl der Bytes zurückzugeben, die für jeden unserer Werte verwendet werden:
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime2 datetime2(7); SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime2 = @thedatetimeoffset; SELECT DATALENGTH(@thedatetimeoffset) AS 'datetimeoffset', DATALENGTH(@thedatetime2) AS 'datetime2';
Ergebnis
+------------------+-------------+ | datetimeoffset | datetime2 | |------------------+-------------| | 10 | 8 | +------------------+-------------+
Wie erwartet 10 Bytes für datetimeoffset und 8 Bytes für datetime2 .
Aber wenn wir sie in varbinary umwandeln , erhalten wir Folgendes:
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime2 datetime2(7); SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime2 = @thedatetimeoffset; SELECT DATALENGTH(CAST(@thedatetimeoffset AS varbinary(16))) AS 'datetimeoffset', DATALENGTH(CAST(@thedatetime2 AS varbinary(16))) AS 'datetime2';
Ergebnis
+------------------+-------------+ | datetimeoffset | datetime2 | |------------------+-------------| | 11 | 9 | +------------------+-------------+
Jedem Wert wird ein zusätzliches Byte hinzugefügt, um die Genauigkeit zu speichern.
Viele Entwickler gehen davon aus, dass die Konvertierung in varbinary ist repräsentativ dafür, wie SQL Server tatsächlich Datums- und Uhrzeitwerte speichert. Dies ist jedoch nur teilweise richtig.
Es stimmt zwar, dass SQL Server seine Datums- und Zeitwerte im Hexadezimalformat speichert, aber dieser Hexadezimalwert enthält nicht wirklich die Genauigkeit. Dies liegt daran, dass die Genauigkeit in der Spaltendefinition enthalten ist. Aber wenn wir in varbinary konvertieren Wie im vorherigen Beispiel wird die Genauigkeit vorangestellt, und dies fügt ein zusätzliches Byte hinzu.
Weitere Einzelheiten darüber, wie diese Datentypen in verschiedenen Kontexten gespeichert werden, finden Sie in den folgenden Artikeln:
- Verstehen der „datetimeoffset“-Speichergröße in SQL Server
- Informationen zur Speichergröße „datetime2“ in SQL Server