web-dev-qa-db-ja.com

SQLServerのDateTime列をDateTimeOffsetに移行します

日時列を持ついくつかの行を持つ古いテーブルがあります。これをdatetimeoffsetに切り替えたいのですが、既存のデータを転送できるようにしたいのです。だから私は次のようなことをしています:

SET IDENTITY_INSERT Table_Temp ON

INSERT INTO Table_Temp
    (Col0, ... ColN,)
SELECT 
    COl0,.... ColN, from 
Table_Original;

SET IDENTITY_INSERT Table_Temp OFF

これは機能しますが、dattimeからdatetimeoffsetへの割り当てを行うとオフセットセットは0になります。幸い、設定したいオフセットは現在のシステムのオフセットです。私はtsqlの第一人者ではありませんが、これを行う簡単な方法を理解できないようです。

変換内でオフセットを設定できるようにしたい。私はc#ユーティリティ(またはPowerShell)を使用することにしましたが、単純にしておきたいと思います。

22
hdz

Datetimeoffsetタイプを認識しているバージョンのSQLServerを使用している場合、次の構文は、サーバーのローカルtzオフセットを取得するために機能します。

select datepart(tz,sysdatetimeoffset())

結果は分単位です。

4
Broam

以下のドキュメントを参照してください。おそらく次のようなものが必要です。

-- up here set the @time_zone variable.

INSERT INTO Table_Temp
    (Col0, ... ColN,)
SELECT 
    COl0, TODATETIMEOFFSET(COLDATE, @time_zone),.... ColN, from 
Table_Original;

から [〜#〜] msdn [〜#〜]

SWITCHOFFSET関数は、UTC値を保持しながら、入力DATETIMEOFFSET値を指定されたタイムゾーンに調整します。構文はSWITCHOFFSET(datetimeoffset_value、time_zone)です。たとえば、次のコードは、現在のシステムのdatetimeoffset値をタイムゾーンGMT + 05:00に調整します。

SELECT SWITCHOFFSET(SYSDATETIMEOFFSET()、 '-05:00');

したがって、現在のシステムのdatetimeoffset値が2009年2月12日10:00:00.0000000 -08:00の場合、このコードは値2009年2月12日13:00:00.0000000-05:00を返します。

TODATETIMEOFFSET関数は、入力された日付と時刻の値のタイムゾーンオフセットを設定します。その構文はTODATETIMEOFFSET(date_and_time_value、time_zone)です。

この関数は、いくつかの点でSWITCHOFFSETとは異なります。まず、入力としてのdatetimeoffset値に制限されません。むしろ、任意の日付と時刻のデータ型を受け入れます。次に、ソース値と指定されたタイムゾーンのタイムゾーンの差に基づいて時刻を調整しようとはせず、代わりに、指定されたタイムゾーンをdatetimeoffset値として入力した日付と時刻の値を返します。

TODATETIMEOFFSET関数の主な目的は、タイムゾーンを認識しないタイプを、指定されたタイムゾーンオフセットによってDATETIMEOFFSETに変換することです。指定された日付と時刻の値がDATETIMEOFFSETの場合、TODATETIMEOFFSET関数は、同じ元のローカルの日付と時刻の値に新しい指定されたタイムゾーンオフセットを加えたものに基づいてDATETIMEOFFSET値を変更します。

たとえば、現在のシステムのdatetimeoffset値は2009年2月12日10:00:00.0000000 -08:00であり、次のコードを実行します。

SELECT TODATETIMEOFFSET(SYSDATETIMEOFFSET()、 '-05:00');

値2009年2月12日10:00:00.0000000-05:00が返されます。 SWITCHOFFSET関数は、入力(-08:00)と指定されたタイムゾーン(-05:00)のタイムゾーンの違いに基づいて時間を調整したため、2009年2月12日13:00:00.0000000-05:00を返したことを思い出してください。 。

前述のように、TODATETIMEOFFSET関数は、任意の日付と時刻のデータ型を入力として使用できます。たとえば、次のコードは、現在のシステムの日付と時刻の値を取得し、タイムゾーンが-00:05のdatetimeoffset値として返します。

SELECT TODATETIMEOFFSET(SYSDATETIME()、 '-05:00');

22
Hogan

タイムゾーンオフセットが同じ年内に変更されるため、DST保存がターゲットタイムゾーンでアクティブになっている場合、これらの変換機能は正しく機能しません。

4
Softlion

以下を使用して、現在のSQLサーバーのオフセットが何であるかを把握できます。

select datediff(MI,getdate(), getutcdate())

30分、さらには15分タイムゾーンもあるため、オフセットは数時間ではなく数分で取得する必要があります。

議事録の値を使用すると、次のようなものを使用して、入力する値を変更できます(履歴的にすべて現地時間として記録されていると仮定)。

select dateadd(mi,datediff(MI,getdate(), getutcdate()), yourDateField)

効率のために、私はそれを一度変数に計算し、それを使用します。違いは変わらないからです。

2
Andrew

これは、すでに提供されている回答のわずかなバリエーションであり、DSTの変更は考慮されていません。ただし、多くの目的には十分な場合があります。

dateadd(minute, -datepart(tz, sysdatetimeoffset()), @legacyDatetime)
1
Tyler Hains

この問題を正しく解決しようとしている人にとって、ここでDSTを考慮することは、それを行うためのツールです。

https://github.com/mj1856/SqlServerTimeZoneSupport

1
Mihail Shishkov