2017-10-16 1 views
2

Ich versuche, eine Zeichenfolge in (in SQL Server) über einen ETL-Auftrag zu konvertieren. Im Grunde würde meine Zeichenfolge ungefähr wie '2017-10-15' aussehen und ich möchte, dass diese in eine DatetimeOffset (vom aktuellen DB-Server) umgewandelt wird.SQL Server DateDiff zwischen zwei Datumsangaben gibt ungenaue Werte zurück

SELECT 
    SWITCHOFFSET(DATEADD(mi, DATEDIFF(MI, GETDATE(), GETUTCDATE()), CAST(@DateInString + ' 00:00:00' AS DATETIMEOFFSET)), DATENAME(tzoffset, SYSDATETIMEOFFSET())) 

Ich habe mit dieser Aussage einige seltsame Probleme bekommen wie die endgültige Ausgabe entweder +1/-1 Minute als den erwarteten fallen würde. Dies geschieht für mindestens alle 10 Datensätze/Millionen. Ich versuchte, das Problem zu nageln, und ich konnte das Problem mit der DATEDIFF() Methode sehen, die +/- 1 Minute zurückbringt.

Dies sollte genau -600 zurückgeben (da mein DB-Server UTC +10 ist). Für einige Datensätze wird jedoch entweder -599 oder 601 zurückgegeben. Ich führe sie als einzelne Select-Anweisung in meiner Stored Procedure aus und gebe sie als Parameter zurück.

Dies ist seltsam, wie SQL zwei unterschiedliche Datetime-Werte für GETDATE() und auf der gleichen SELECT-Anweisung erkennen konnte.

Gibt es eine Möglichkeit, SQL zu zwingen, genau dieselben Daten in diesen DATEDIFF Parametern zu erhalten, oder fehle ich hier etwas? Vielen Dank im Voraus

Ich benutze SQL Server 2014 (v12.0).

Stored Procedure:

CREATE PROCEDURE dbo.SPConvertDateTimeOffset 
    @DateInString VARCHAR(10), 
    @DateTimeOffset_Value DATETIMEOFFSET OUTPUT, 
    @Datediff_Value INT OUTPUT 
AS 
BEGIN 
    -- This line returns +/- 1 
    SELECT @Datediff_Value = DATEDIFF(MI, GETDATE(), GETUTCDATE()) 

    SELECT @DateTimeOffset_Value = SWITCHOFFSET(DATEADD(mi, @Datediff_Value, CAST(@DateInString + ' 00:00:00' AS DATETIMEOFFSET)), DATENAME(tzoffset, SYSDATETIMEOFFSET())) 
END 
+0

Wenn Sie dies viele, viele Male tun, dann sind 'getdate()' und 'getutcdate()' möglicherweise um einige Millisekunden aus. –

+0

Spielt es wirklich eine Rolle? Weil, ich bekomme das datediff nur für den Minutenteil. Auch wenn ich es mehrmals mache, sollte es mir idealerweise den gleichen Datetime-Wert geben. Haben Sie jedoch einen Hinweis darauf, warum es Unterschiede in Millisekunden gibt, wenn ich es mehrmals mache? – Bharathi

+3

Es kann wichtig sein, weil 'datediff()' * Grenzen * zwischen den Zeiten misst. –

Antwort

0

@GordonLinoff hat erklärt, warum dies geschieht: Da Funktionen bei leicht ausgeführt werden zu unterschiedlichen Zeiten können sie eine andere Minute zurückgeben.

um zu umgehen, versuchen Sie dies:

DECLARE @DateTimeOffset_Value Datetimeoffset 
DECLARE @Datediff_Value INT, @DateInString VARCHAR(10) 
SET @DateInString = CONVERT(VARCHAR, GETDATE(), 112) 
SET @DateTimeOffset_Value = TODATETIMEOFFSET(@DateInString, DATENAME(tzoffset,SYSDATETIMEOFFSET())) 
SET @Datediff_Value = DATEDIFF(MI, @DateInString, @DateTimeOffset_Value) 
SELECT @DateInString, @DateTimeOffset_Value, @Datediff_Value 

Es ist nicht das aktuelle Datum Vergleiche zu verwenden ist.

Hinweis:, dass während der Zeit, als sich die Lichteinsparung am Tag ändert, ein anderer Wert als erwartet erwartet wird, abhängig davon, wann genau der Code ausgeführt wurde.

Weitere Lösungen zum Umgang mit DTS-Änderungen finden Sie unter https://dba.stackexchange.com/questions/28187/how-can-i-get-the-correct-offset-between-utc-and-local-times-for-a-date-that-is.

+0

Ich versuche immer noch, einen Verweis/eine Verbindung von MSDN zu finden, warum GetDate() und GetUTCDate unterschiedliche Datetime unter einzelner Auswahl zurückgibt. Diese Antwort löste jedoch mein Problem beim Konvertieren von datetimetimeoffset. Vielen Dank. – Bharathi

+1

@Bharathi - Ich konnte keine Microsoft-Referenzen finden, aber es gibt ein paar bestehende Fragen zu SO, die sich mit dem gleichen Problem befassen: https://Stackoverflow.com/questions/6036223/will-getutcdate-return-the-same-value- if-used-two-in-the-same-Anweisung/6036783 # 6036783 und https://stackoverflow.com/questions/3620105/sql-server- intrigued-by-getdate/3620119#3620119 – Alex

0

Die beiden Funktionen nicht gleichzeitig ausgeführt werden. Also etwa 1 mal in 100.000 (in deinem Test) sind die Zeiten auf gegenüberliegenden Seiten einer winzigen Grenze.

Wenn Sie nur die Zeitzone wollen, könnten Sie versuchen:

wählen Datumsteil (tz, SYSDATETIMEOFFSET())

Verwandte Themen