2010-01-05 3 views
20

Ho una vecchia tabella con poche righe che ha una colonna datetime. Voglio passare a datetimeoffset ma voglio poter trasferire i dati già esistenti. Così sto facendo qualcosa di simile:Migrare la colonna DateTime di SQL Server a 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 

Questo funziona ma il set di offset è 0 quando faccio il dattime a datetimeoffset assegnazione. Fortunatamente l'offset su cui voglio impostarlo è l'offset del sistema attuale. Non sono un guru del tsql ma non riesco a capire un modo semplice per farlo.

Voglio essere in grado di impostare l'offset all'interno della conversione. Stavo per ricorrere a un programma di utilità C# (o PowerShell), ma preferirei mantenerlo semplice.

+0

--- Grazie ragazzi, avrei dovuto essere chiaro che ho semplicemente voluto aggiungere l'offset senza modificare il tempo stesso. Ma voi ragazzi mi avete portato lì! ;) – hdz

risposta

4

Se si utilizza una versione di SQL Server che sa di tipo datetimeoffset, questa sintassi funzionerà per voi ottenere l'offset del server tz locale:

select datepart(tz,sysdatetimeoffset())

Il risultato è in MINUTES.

+0

Grazie per quello, esattamente quello di cui avevo bisogno. Stanno usando così tanti termini sovrapposti ora che è diventato difficile persino cercare i documenti ... –

2

È possibile determinare quale sia l'offset del server SQL corrente che utilizza quanto segue.

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

è necessario per ottenere l'offset in pochi minuti e non ore dato che ci sono un certo numero di mezz'ora e anche un fuso orario quarto d'ora.

Utilizzando il valore dei minuti, è possibile modificare i valori che vanno in (ammesso che sono stati storicamente tutte registrate come ora locale) utilizzando qualcosa come

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

Per l'efficienza avrei calcolare una volta in una variabile e l'uso quello, poiché la differenza non cambierà.

+2

non funziona su date storiche se è necessario tenere conto dell'ora legale. Destra? Stai cercando il tuo attuale offset UTC basato su getdate e poi aggiungilo a un campo di date storiche. Ma l'offset cambia se si desidera tenere conto dell'ora legale. L'ora dello standard orientale è UTC-5, ma l'ora legale di Eastern Day è UTC-4. Se vuoi convertire le date storiche devi essere consapevole delle transizioni dell'ora legale. (Mi viene il mal di testa solo a pensarci). –

+0

Correggere, quindi spostare i dati cronologici in lotti, quindi tenere conto del fatto che l'anno ha un diverso momento nel tempo in cui è stato modificato. – Andrew

+0

Come andresti a trovare l'offset della data storica? – Jeremy

22

Vedi sotto per i doc, probabilmente si desidera qualcosa di simile:

-- up here set the @time_zone variable. 

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

Da MSDN

La funzione SWITCHOFFSET regola un valore DateTimeOffset ingresso a un fuso orario specificato , preservando la Valore UTC. La sintassi è SWITCHOFFSET (datetimeoffset_value, time_zone). Ad esempio, il codice seguente regola il valore datetimeoffset sistema attuale fuso orario GMT +05: 00:

SELEZIONA SWITCHOFFSET (SYSDATETIMEOFFSET(), '-05: 00');

Quindi, se l'attuale sistema valore datetimeoffset è 12 febbraio 2009 10: 00: 00.0000000 -08: 00, questo codice restituisce il valore 12 febbraio 2009 13: 00: 00.0000000 -05: 00.

La funzione TODATETIMEOFFSET imposta lo scostamento del fuso orario di una data di immissione e il valore temporale . La sua sintassi è TODATETIMEOFFSET (date_and_time_value, time_zone).

Questa funzione è diversa da SWITCHOFFSET in diversi modi. Innanzitutto, non è limitato a un valore datetimeoffset come input; piuttosto accetta qualsiasi data e ora di dati tipo.In secondo luogo, esso non tenta di regolare l'ora in base al fuso orario differenza tra il valore di origine e il fuso orario specificato ma invece restituisce semplicemente la data di input e valore di tempo con il fuso orario specificato come valore datetimeoffset .

Lo scopo principale della funzione TODATETIMEOFFSET vale a convertire formati non fuso orario consapevoli di datetimeoffset dal tempo determinato differenza di fuso. Se la data e l'ora data valore è un datetimeoffset, la funzione TODATETIMEOFFSET cambia valore datetimeoffset base alla stessa data locale originale e il valore temporale e la nuova proposta fuso offset.

Ad esempio, l'attuale sistema di valore datetimeoffset è il 12 febbraio 2009 10: 00: 00.0000000 -08: 00, e si eseguire il seguente codice:

SELEZIONA TODATETIMEOFFSET (SYSDATETIMEOFFSET(), '-05: 00');

Il valore 12 febbraio 2009 10: 00: 00.0000000 -05: 00 viene restituito. Ricordate che la funzione SWITCHOFFSET restituito 12 febbraio 2009 13: 00: 00.0000000 -05: 00 perché modificare il tempo in base alle differenze di fuso orario tra l'ingresso (-08: 00) e il fuso orario specificato (-05: 00).

Come accennato in precedenza, è possibile utilizzare la funzione TODATETIMEOFFSET con qualsiasi tipo di dati di data e ora come input. Ad esempio, il seguente codice ha la data corrente sistema e valore temporale e restituisce come valore datetimeoffset con un fuso -00: 05:

SELEZIONA TODATETIMEOFFSET (SYSDATETIME(), '-05: 00');

+1

Un commento su questo v. Vecchio post. Il fuso orario e l'offset della data sono a cose diverse. Il fuso orario prende in considerazione l'ora legale, mentre l'offset è appena sfalsato. –

4

Queste funzioni di conversione non funzioneranno correttamente se il salvataggio dell'ora legale è attivo nel fuso orario target, poiché lo scostamento del fuso orario cambia nello stesso anno.

+2

Come lo faresti correttamente, per prendere in considerazione l'ora legale? – Jeremy

0

Questa è una leggera variazione di una risposta già fornita, e non tiene conto di modifiche dell'ora legale.Tuttavia, potrebbe essere abbastanza buono per vari scopi:

dateadd(minute, -datepart(tz, sysdatetimeoffset()), @legacyDatetime)