it-swarm.com.de

DateTime2 vs. DateTime in SQL Server

Welcher: 

ist die empfohlene Methode zum Speichern von Datum und Uhrzeit in SQL Server 2008+?

Ich bin mir der Unterschiede in der Genauigkeit (und des Speicherplatzes wahrscheinlich) bewusst, aber wenn ich sie vorerst ignoriere, gibt es ein Best-Practice-Dokument, wann Sie was verwenden sollten, oder sollten wir vielleicht nur datetime2 verwenden?

667
Mikeon

Die MSDN-Dokumentation für datetime empfiehlt die Verwendung von datetime2 . Hier ist ihre Empfehlung:

Verwenden Sie die Variablen time, date, datetime2 und datetimeoffset Datentypen für neue Arbeit. Diese Typen stimmen mit der SQL .__ überein. Standard. Sie sind tragbarer . time, datetime2 und datetimeoffset sorgen für mehr sekundengenauigkeit . datetimeoffset gibt die Zeitzone an Unterstützung für global bereitgestellte Anwendungen.

datetime2 hat einen größeren Datumsbereich, eine höhere Standard-Bruchteilgenauigkeit und eine optionale, vom Benutzer angegebene Genauigkeit. Abhängig von der vom Benutzer angegebenen Genauigkeit wird möglicherweise weniger Speicherplatz benötigt. 

557
Adam Porad

DATETIME2 hat einen Datumsbereich von "0001/01/01" bis "9999/12/31", während der Typ DATETIME nur das Jahr 1753-9999 unterstützt.

Falls erforderlich, kann DATETIME2 zeitlich genauer sein. DATETIME ist auf 3 1/3 Millisekunden begrenzt, während DATETIME2 auf 100ns genau sein kann.

Beide Typen sind in .NET System.DateTime zugeordnet - kein Unterschied.

Wenn Sie die Wahl haben, würde ich empfehlen, DATETIME2 wann immer möglich zu verwenden. Ich sehe keine Vorteile bei der Verwendung von DATETIME (außer für die Abwärtskompatibilität) - Sie haben weniger Probleme (Datumsangaben liegen außerhalb des Bereichs und stören so).

Plus: Wenn Sie nur das Datum (ohne Zeitangabe) benötigen, verwenden Sie DATE - es ist genauso gut wie DATETIME2 und spart auch Platz! :-) Gleiches gilt nur für die Zeit - verwenden Sie TIME. Dafür sind diese Typen da!

454
marc_s

datetime2 gewinnt in den meisten Aspekten außer (Kompatibilität mit alten Apps)

  1. größerer Wertebereich 
  2. besser Genauigkeit
  3. kleinerer Speicherplatz (wenn optionale vom Benutzer angegebene Genauigkeit angegeben ist)

SQL Date and time data types compare - datetime,datetime2,date,TIME

bitte beachten Sie die folgenden Punkte

  • Syntax
    • datetime2 [(Sekundengenauigkeit => Blick unter Speichergröße)]
  • Präzisionswaage
    • 0 bis 7 Ziffern mit einer Genauigkeit von 100 ns. 
    • Die Standardgenauigkeit beträgt 7 Stellen.
  • Speichergröße
    • 6 Bytes für eine Genauigkeit von weniger als 3; 
    • 7 Bytes für Genauigkeit 3 ​​und 4. 
    • Alle anderen Genauigkeiten benötigen 8 Byte.
  • DateTime2 (3) haben dieselbe Anzahl von Stellen wie DateTime, benötigen jedoch 7 Byte Speicherplatz anstelle von 8 Byte ( SQLHINTS- DateTime Vs DateTime2 )
  • Weitere Informationen finden Sie unter datetime2 (Transact-SQL-MSDN-Artikel)

bildquelle: MCTS Training Kit für Selbststudium (Prüfung 70-432): Microsoft® SQL Server® 2008 - Implementierung und Wartung Kapitel 3: Tabellen -> Lektion 1: Tabellen erstellen -> Seite 66

175
Iman Abidi

Ich stimme mit @marc_s und @Adam_Poward überein - DateTime2 ist die bevorzugte Methode, die sich vorwärts bewegt. Es hat einen breiteren Datumsbereich, eine höhere Genauigkeit und verwendet gleiche oder weniger Speicherplatz (je nach Genauigkeit). 

Eine Sache, die der Diskussion jedoch entgangen ist ...
@ Marc_s besagt: Both types map to System.DateTime in .NET - no difference there. Dies ist korrekt, die Umkehrung ist jedoch nicht wahr... und es ist wichtig, wenn Datumsbereichssuchen ausgeführt werden (z. B. "Finde alle Datensätze, die am 05.05.2010 geändert wurden"). 

Die .NET-Version von Datetime hat einen ähnlichen Bereich und eine ähnliche Genauigkeit wie DateTime2. Beim Abbilden einer .net Datetime auf die alte SQL DateTime erfolgt eine implizite Rundung. Die alte SQL DateTime ist auf 3 Millisekunden genau. Dies bedeutet, dass 11:59:59.997 so nah ist, wie Sie das Ende des Tages erreichen können. Alles, was höher ist, wird auf den nächsten Tag aufgerundet.

Versuche dies :

declare @d1 datetime   = '5/5/2010 23:59:59.999'
declare @d2 datetime2  = '5/5/2010 23:59:59.999'
declare @d3 datetime   = '5/5/2010 23:59:59.997'
select @d1 as 'IAmMay6BecauseOfRounding', @d2 'May5', @d3 'StillMay5Because2msEarlier'

Das Vermeiden dieser impliziten Rundung ist ein wichtiger Grund, zu DateTime2 zu wechseln. Die implizite Rundung von Datumsangaben führt eindeutig zu Verwirrung:

102
EBarr

Fast alle Antworten und Kommentare haben die Vor- und Nachteile schwer getroffen. Hier ist eine Zusammenfassung aller bisherigen Vor- und Nachteile sowie einiger entscheidender Nachteile (in # 2 unten), die ich nur einmal oder gar nicht erwähnt habe.

  1. PROS:

1.1. ISO-konform (ISO 8601) (obwohl ich nicht weiß, wie dies in der Praxis zum Tragen kommt).

1.2. Ein größerer Bereich (1.1.10001 bis 31.12.9999 gegenüber 1.1.1753 bis 31.12.9999) (obwohl der zusätzliche Bereich, der alle vor dem Jahr 1753 liegt, wahrscheinlich nicht verwendet wird, außer zum Beispiel.) in historischen, astronomischen, geologischen usw. Apps).

1.3. Entspricht genau dem Bereich des Typs DateTime in .NET (obwohl beide ohne spezielle Codierung vor und zurück konvertieren, wenn die Werte innerhalb des Bereichs und der Genauigkeit des Zieltyps liegen, mit Ausnahme von Con # 2.1, unter dem sonst Fehler/Rundungen auftreten).

1.4. Höhere Präzision (100 Nanosekunden, alias 0,000,000,1 Sek. Gegenüber 3,33 Millisekunden, alias 0,003,33 Sek.) (Obwohl die höhere Präzision mit Ausnahme von Ex. In technischen/wissenschaftlichen Apps wahrscheinlich nicht verwendet wird).

1.5. Wenn konfiguriert für ähnlich (wie in 1 Millisekunde nicht "gleich" (wie in 3,33 Millisekunden), wie von Iman Abidi behauptet) Präzision als DateTime, wird weniger Platz benötigt (7 vs. 8 Bytes), aber dann würden Sie natürlich den Präzisionsvorteil verlieren, der wahrscheinlich einer der beiden (der andere ist der Bereich) ist, der am meisten angepriesen wird, obwohl wahrscheinlich nicht benötigter Nutzen).

  1. Nachteile:

2.1. Wenn Sie einen Parameter an .NET SqlCommand übergeben, müssen Sie System.Data.SqlDbType.DateTime2 Angeben, wenn Sie möglicherweise einen Wert außerhalb des Bereichs und/oder der Genauigkeit von SQL Server DateTime übergeben, da dieser standardmäßig verwendet wird zu System.Data.SqlDbType.DateTime.

2.2. Kann nicht implizit/einfach in einen numerischen Gleitkommawert (Anzahl der Tage seit der minimalen Datums-/Uhrzeitangabe) konvertiert werden, um mit numerischen Werten und Operatoren in SQL Server-Ausdrücken Folgendes zu tun:

2.2.1. Addiere oder subtrahiere die Anzahl der Tage oder Teiltage. Hinweis: Die Verwendung von DateAdd als Problemumgehung ist nicht trivial, wenn Sie mehrere, wenn nicht alle Teile der Datums- und Uhrzeitangabe berücksichtigen müssen.

2.2.2. Berechnen Sie die Differenz zwischen zwei Datums- und Uhrzeitangaben für die Berechnung des Alters. Hinweis: Sie können stattdessen nicht einfach die Funktion DateDiff von SQL Server verwenden, da sie age nicht berechnet, wie die meisten Leute es erwarten würden, wenn die beiden Datumszeiten einen Kalender/eine Uhrzeit kreuzen. Zeitgrenze der angegebenen Einheiten, wenn selbst für einen winzigen Bruchteil dieser Einheit die Differenz 1 dieser Einheit gegen 0 zurückgegeben wird. Beispiel: Die DateDiff in Day ist zwei Datumszeiten im Abstand von nur 1 Millisekunde ergeben 1 vs. 0 (Tage), wenn sich diese Datumszeiten an verschiedenen Kalendertagen befinden (z. B. „1999-12-31 23: 59: 59.9999999“ und „2000-01-01 00:00“) : 00.0000000 ”). Die gleiche Differenz von Datum und Uhrzeit von 1 Millisekunde, wenn sie so verschoben wird, dass sie keinen Kalendertag überschreitet, gibt ein "DateDiff" in Day von 0 (Tagen) zurück.

2.2.3. Nehmen Sie das Avg von Datum und Uhrzeit (in einer aggregierten Abfrage), indem Sie einfach zuerst in "Float" und dann wieder in DateTime konvertieren.

HINWEIS: Um DateTime2 In eine Zahl umzuwandeln, müssen Sie die folgende Formel verwenden, bei der weiterhin davon ausgegangen wird, dass Ihre Werte nicht unter dem Jahr 1970 liegen (was bedeutet, dass Sie den gesamten zusätzlichen Bereich plus weitere 217 verlieren) Jahre Hinweis: Möglicherweise können Sie die Formel nicht einfach anpassen, um zusätzlichen Bereich zu berücksichtigen, da möglicherweise Probleme mit dem numerischen Überlauf auftreten.

25567 + (DATEDIFF(SECOND, {d '1970-01-01'}, @Time) + DATEPART(nanosecond, @Time) / 1.0E + 9) / 86400.0 - Quelle: “ https://siderite.blogspot.com/2015/08/how-to-translate-t-sql-datetime2-to.html

Natürlich können Sie auch zuerst Cast bis DateTime (und gegebenenfalls wieder zurück zu DateTime2), Aber Sie würden die Genauigkeit und den Bereich verlieren (alle vor dem Jahr 1753) ) Vorteile von DateTime2 gegenüber DateTime, die wahrscheinlich die 2 größten und gleichzeitig die 2 am wenigsten benötigten sind, was die Frage aufwirft, warum Sie sie verwenden, wenn Sie die impliziten/einfachen Konvertierungen verlieren Gleitkommazahl (Anzahl der Tage) für Addition/Subtraktion/"Alter" (vs. DateDiff)/Avg berechnet den Vorteil, der meiner Erfahrung nach ein großer Vorteil ist.

Übrigens ist das Avg der Datums- und Uhrzeitangaben (oder zumindest sollte ein wichtiger Anwendungsfall. a) Neben der Verwendung zum Abrufen der Durchschnittsdauer, wenn Datumszeiten (da eine gemeinsame Basis-Datumszeit) zur Darstellung der Dauer verwendet werden (eine übliche Vorgehensweise), ist es auch nützlich, eine Statistik vom Typ Dashboard zu erhalten, die angibt, wie hoch die Durchschnittsdauer ist. Die Uhrzeit befindet sich in der Datums-/Uhrzeitspalte eines Bereichs/einer Gruppe von Zeilen. c) Eine standardmäßige (oder zumindest sollte standardmäßige) Ad-hoc-Abfrage zum Überwachen/Behandeln von Werten in einer Spalte, die möglicherweise nicht mehr gültig sind und/oder veraltet sein müssen Für jeden Wert werden die Anzahl der Vorkommen und (falls verfügbar) die Min-, Avg- und Max -Datum-Zeit-Stempel aufgelistet, die diesem Wert zugeordnet sind.

16
Tom

DateTime2 führt zu Chaos, wenn Sie ein Access-Entwickler sind, der Now () in das betreffende Feld schreiben möchte. Es wurde nur eine Migration von Access -> SQL 2008 R2 durchgeführt, und es wurden alle datetime-Felder in DateTime2 eingefügt. Anhängen eines Datensatzes mit Now () als ausgesprochenen Wert. Es war okay am 1.1.2012 14:53:04 PM, aber nicht am 10.01.2012 14:53:04 Uhr. 

Einmal machte der Charakter den Unterschied. Ich hoffe es hilft jemandem.

15
Rhett A Brown

Hier ein Beispiel, das Ihnen die Unterschiede in der Speichergröße (Bytes) und der Genauigkeit zwischen smalldatetime, datetime, datetime2 (0) und datetime2 (7) zeigt:

DECLARE @temp TABLE (
    sdt smalldatetime,
    dt datetime,
    dt20 datetime2(0),
    dt27 datetime2(7)
)

INSERT @temp
SELECT getdate(),getdate(),getdate(),getdate()

SELECT sdt,DATALENGTH(sdt) as sdt_bytes,
    dt,DATALENGTH(dt) as dt_bytes,
    dt20,DATALENGTH(dt20) as dt20_bytes,
    dt27, DATALENGTH(dt27) as dt27_bytes FROM @temp

die zurückkehrt

sdt                  sdt_bytes  dt                       dt_bytes  dt20                 dt20_bytes  dt27                         dt27_bytes
2015-09-11 11:26:00  4          2015-09-11 11:25:42.417  8         2015-09-11 11:25:42  6           2015-09-11 11:25:42.4170000  8

Wenn ich also Informationen bis zur Sekunde speichern möchte, aber nicht bis zur Millisekunde, kann ich jeweils 2 Byte speichern, wenn ich datetime2 (0) anstelle von datetime oder datetime2 (7) verwende.

13
Baodad

während precision mit datetime2 erhöht wird, unterstützen einige Clients Datum, Zeit oder DatumZeit2 nicht und zwingen Sie dazu Konvertieren Sie in ein String-Literal. Insbesondere erwähnt Microsoft "Downlevel" -ODBC-, OLE - DB-, JDBC- und SqlClient-Probleme mit diesen Datentypen und verfügt über ein chart , das zeigt, wie jeder Typ den Typ zuordnen kann. 

Wenn der Wert Kompatibilität über der Genauigkeit liegt, verwenden Sie datetime

8
FistOfFury

Die Interpretation von Datumszeichenfolgen in datetime und datetime2 kann sich auch unterscheiden, wenn DATEFORMAT-Einstellungen verwendet werden, die nicht in den USA sind. Z.B.

set dateformat dmy
declare @d datetime, @d2 datetime2
select @d = '2013-06-05', @d2 = '2013-06-05'
select @d, @d2

Dies gibt 2013-05-06 (d. H. 6. Mai) für datetime und 2013-06-05 (d. H. 5. Juni) für datetime2 zurück. Wenn jedoch dateformat auf mdy gesetzt ist, geben sowohl @d als auch @d22013-06-05 zurück.

Das Verhalten von datetime scheint mit der MSDN-Dokumentation von SET DATEFORMAT im Widerspruch zu stehen: Einige Zeichenkettenformate, beispielsweise ISO 8601, werden unabhängig von der Einstellung DATEFORMAT interpretiert. Offensichtlich nicht wahr!

Bis ich davon gebissen wurde, hatte ich immer gedacht, dass yyyy-mm-dd-Daten unabhängig von den Sprach-/Ländereinstellungen nur richtig gehandhabt werden würden.

7
Richard Fawcett

Alte Frage ... Aber ich möchte hier etwas hinzufügen, das noch nicht erwähnt wurde ... (Hinweis: Dies ist meine eigene Beobachtung, fragen Sie also nicht nach einem Hinweis)

Datetime2 ist schneller, wenn es in Filterkriterien verwendet wird.

TLDR:

In SQL 2016 hatte ich eine Tabelle mit hunderttausend Zeilen und einer Datetime-Spalte ENTRY_TIME, da die genaue Zeit bis zu Sekunden gespeichert werden musste. Bei der Ausführung einer komplexen Abfrage mit vielen Joins und einer Unterabfrage wurde die Klausel where wie folgt verwendet:

WHERE ENTRY_TIME >= '2017-01-01 00:00:00' AND ENTRY_TIME < '2018-01-01 00:00:00'

Die Abfrage war anfangs in Ordnung, als es Hunderte von Zeilen gab, aber als die Anzahl der Zeilen zunahm, begann die Abfrage mit diesem Fehler:

Execution Timeout Expired. The timeout period elapsed prior
to completion of the operation or the server is not responding.

Ich habe die where-Klausel entfernt, und die Abfrage wurde unerwartet in 1 Sekunde ausgeführt, obwohl jetzt ALLE Zeilen für alle Datumsangaben abgerufen wurden. Ich führe die innere Abfrage mit where-Klausel aus, und es dauerte 85 Sekunden, und ohne where-Klausel dauerte es 0,01 Sekunden.

Ich bin hier für dieses Thema auf viele Threads gestoßen, da datetime-Filterleistung

Ich habe die Abfrage etwas optimiert. Aber die wirkliche Geschwindigkeit, die ich bekam, war, die datetime-Spalte in datetime2 zu ändern.

Nun dauert dieselbe Abfrage, die zuvor abgelaufen ist, weniger als eine Sekunde.

prost

5
Khan

Gemäß diesem Artikel müssen Sie DateTime2 (3) verwenden, wenn Sie die gleiche Genauigkeit von DateTime verwenden möchten. Dies sollte Ihnen die gleiche Genauigkeit bieten, ein Byte weniger beanspruchen und einen erweiterten Bereich bieten. 

4
jKlaus

Ich bin gerade über einen weiteren Vorteil für DATETIME2 gestolpert: Dadurch wird ein Fehler im Python-Modul adodbapi vermieden, der bei der Übergabe eines datetime-Werts der Standardbibliothek explodiert, der nicht-null Mikrosekunden für eine DATETIME-Spalte hat DATETIME2.

3
Bob Kline
Select ValidUntil + 1
from Documents

Das obige SQL funktioniert nicht mit einem DateTime2-Feld .

Das Hinzufügen von 1 für den nächsten Tag ist etwas, was Entwickler seit Jahren mit Terminen tun. Microsoft verfügt jetzt über ein neues neues datetime2-Feld, das diese einfache Funktionalität nicht verarbeiten kann.

"Lass uns diesen neuen Typ verwenden, der schlechter ist als der alte", glaube ich nicht!

0
Paul McCarthy

Ich denke, DATETIME2 ist der bessere Weg, um das Datum zu speichern, weil es mehr Effizienz hat als Das DATETIME. In SQL Server 2008 können Sie DATETIME2 verwenden, es speichert ein Datum und eine Uhrzeit, benötigt 6-8 Bytes zum Speichern und hat eine Genauigkeit von 100 Nanosekunden. Wer also größere Zeitgenauigkeit benötigt, möchte DATETIME2.

0
James