In der Dokumentation wird ausdrücklich darauf hingewiesen, dass die einzigen sicheren Formate diejenigen sind, die ich zu Beginn der Frage demonstriert habe:
yyyyMMdd -- unseparated, date only
yyyy-MM-ddThh:mm:ss.fff -- date dash separated, date/time separated by T
Vor kurzem wurde ich jedoch darauf aufmerksam gemacht, dass es ein drittes Format gibt, das für alle Sprach- und Datumsformateinstellungen gleichermaßen immun ist:
yyyyMMdd hh:mm:ss.fff -- unseparated date, no T separator
TL; DR: Das ist wahr. Für datetime
und smalldatetime
.
Lesen Sie weiter für die längere Version und über so viele Beweise, wie Sie bekommen werden.
Es gibt eine Lücke, die dies erklärt - während der Haupttextkörper das yyyyMMdd hh:...
Format nicht als sicher für transponierte Sprach- oder Datumsformatinterpretationen anerkennt , gibt es einen kleinen Klappentext, der besagt, dass der Datumsanteil einer solchen Zeichenfolge abhängig von den Datumsformateinstellungen nicht validiert wird:
Es ist mir eher unähnlich, die Dokumentation nur beim Wort zu nehmen. Man kann sagen, ich bin ein bisschen skeptisch. Und auch hier ist die Sprache nicht eindeutig - es geht nur um die Kombination von Datum und Uhrzeit, ohne den Raum explizit auszulesen (das könnte, soweit ich weiß, ein Wagenrücklauf sein). Es heißt auch, dass es nicht mehrsprachig ist, was bedeutet, dass es in bestimmten Sprachen fehlschlagen kann, aber wir werden in Kürze herausfinden, dass dies auch falsch ist.
Ich wollte also beweisen, dass keine Kombination von Sprache / Datumsformat dazu führen kann, dass dieses spezielle Format fehlschlägt.
Zuerst habe ich für jede Sprache einen kleinen Block mit dynamischem SQL erstellt:
EXEC sys.sp_executesql @sql, N'@lang sysname', N'us_english';
Dies erzeugte 34 Zeilen der Ausgabe wie folgt:
EXEC sys.sp_executesql @sql, N'@lang sysname', N'us_english';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'Deutsch';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'Français';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'日本語';
...
EXEC sys.sp_executesql @sql, N'@lang sysname', N'简体中文';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'Arabic';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'ไทย';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'norsk (bokmål)';
Ich habe diese Ausgabe in ein neues Abfragefenster kopiert und darüber den folgenden Code generiert, mit dem hoffentlich in mindestens einem Fall versucht wird, dasselbe Datum (den 13. März) auf den 3. Tag des 13. Monats umzustellen:
DECLARE @sql nvarchar(max) = N'
SET LANGUAGE @lang;
SET DATEFORMAT ydm;
SELECT @@LANGUAGE, CONVERT(datetime, ''20170313 23:22:21.020'');';
Nein, jede Sprache funktioniert nur in ydm
. Ich habe auch jedes andere Format ausprobiert und auch jeden Datums- / Zeitdatentyp. Jedes Mal 34 erfolgreiche Umbauten bis zum 13. März.
Also gebe ich @AndriyM und @ErikE zu, dass es tatsächlich ein drittes sicheres Format gibt. Ich werde dies für zukünftige Posts im Hinterkopf behalten, aber ich habe die Trommeln an so vielen Stellen auf die anderen beiden geschlagen, dass ich sie jetzt nicht alle aufspüren und korrigieren werde.
Im weiteren Sinne würden Sie denken, dies wäre sicher, aber nein:
yyyyMMddThh:mm:ss.fff -- unseparated date, T separator
Ich denke, in jeder Sprache ergibt dies das Äquivalent von:
Meldung 241, Ebene 16, Status 1, Zeile 8 Die
Konvertierung ist fehlgeschlagen, wenn Datum und / oder Uhrzeit aus der Zeichenfolge konvertiert wurden.
Die Vollständigkeit halber gibt es ein viertes sicheres Format, aber es ist nur sicher für Conversions zu den neueren Datum / Zeit - Typen ( date
, datetime2
, datetimeoffset
). In diesen Fällen können die Spracheinstellungen nicht stören:
yyyy-MM-dd hh:mm:...
Ich rate jedoch dringend von seiner Verwendung ab, da es nur für die neueren Typen funktioniert und die alten nach meiner Erfahrung immer noch in großem Umfang verwendet werden. Warum müssen die Bindestriche an anderen Stellen (oder tatsächlich im selben Code, wenn sich der Datentyp ändert) entfernt werden?
SET LANGUAGE Deutsch;
DECLARE @dashes char(10) = '2017-03-07 03:34';
DECLARE @d date = @dashes, @dt datetime = @dashes, @dt2 datetime2 = @dashes;
SELECT DATENAME(MONTH,@d), DATENAME(MONTH,@dt), DATENAME(MONTH,@dt2);
Sogar bei der gleichen Quellzeichenfolge ergaben die Konvertierungen ganz unterschiedliche Ergebnisse:
März Juli März
Das Format, das für datetime ( yyyyMMdd
) funktioniert, funktioniert auch immer für date und die anderen neuen Typen. Also, IMHO, benutze das einfach immer. Mit dem dritten Format für Typen mit Datum / Uhrzeit ( yyyyMMdd hh:...
) können Sie tatsächlich konsistenter sein - auch wenn die Datumskomponente immer etwas weniger lesbar ist.
Jetzt brauche ich nur ein paar Jahre, um mir die Gewohnheit zu geben, die drei sicheren Formate zu demonstrieren , wenn ich über die Zeichenfolgendarstellung von Datumsangaben spreche.