2013-08-13 11 views
11

Data una tabella SQL con una colonna DateTime e circa 100k righe di varie date (valori PST ora locale) degli ultimi 3 anni, qual è la strategia migliore per migrare tali valori di colonna su DateTimeOffset per "aggiungere" l'offset utc tz mancante Informazioni?Migrazione di valori SQL DateTime memorizzati a best practice DateTimeOffset?

I valori DateTime esistenti sono stati memorizzati senza alcun fuso orario/dettagli offset dell'utc. Le date memorizzate sono sempre rappresentative del fuso orario del Pacifico (-800 o -700 in base all'ora legale). Obiettivo è quello di aggiungere retroattivamente il tz di offset a tutti i dati esistenti con il presupposto che la data è venuto da ora del Pacifico (qualunque sia la corretta compensazione era al momento specificato dalla data di)

  • all'interno di SQL che cosa è la migliore pratica per questo tipo di migrazione senza perdere dati o modificare i valori esistenti?

  • porta al passo successivo, qual è il metodo più efficiente per migrare un intero database di dimensioni moderate (~ 100 GB in ~ 100 tabelle con 2 colonne DateTime per tabella) per usare DateTimeOffset colonne e valori?

  • Cosa succede ai dati di data e ora di registrazione/durante la data di commutazione PST/PDT? C'è una perdita di dati che accade?

SQL Server 2008 + C# 4.5

Se questa non è la zona giusta per favore mi punto nella giusta direzione, grazie!

Modifica: Yay, tempo di taglia.

+1

Essere semplicemente "quel tipo", ma in realtà non chiamerei 100 GB un DB di dimensioni medie, che in realtà è abbastanza grande. –

risposta

5

L'ora legale non è sempre una scienza esatta. Per esempio. c'era un rule change in 2007 per il periodo utilizzato in Nord America. Per questo motivo, suggerirei di compilare una tabella con le date pertinenti. Per esempio. per 2000-2013:

-- Populate a table with PST daylight saving start/end times 
-- Example data for 2000-2013 - sourced from 
-- http://www.timeanddate.com/worldclock/timezone.html?n=137 
CREATE TABLE dst (start DateTime, [end] DateTime); 
INSERT INTO dst (start, [end]) VALUES ('02:00 2 Apr 2000', '02:00 29 Oct 2000'); 
INSERT INTO dst (start, [end]) VALUES ('02:00 1 Apr 2001', '02:00 28 Oct 2001'); 
INSERT INTO dst (start, [end]) VALUES ('02:00 7 Apr 2002', '02:00 27 Oct 2002'); 
INSERT INTO dst (start, [end]) VALUES ('02:00 6 Apr 2003', '02:00 26 Oct 2003'); 
INSERT INTO dst (start, [end]) VALUES ('02:00 4 Apr 2004', '02:00 31 Oct 2004'); 
INSERT INTO dst (start, [end]) VALUES ('02:00 3 Apr 2005', '02:00 30 Oct 2005'); 
INSERT INTO dst (start, [end]) VALUES ('02:00 2 Apr 2006', '02:00 29 Oct 2006'); 
INSERT INTO dst (start, [end]) VALUES ('02:00 11 Apr 2007', '02:00 4 Oct 2007'); 
INSERT INTO dst (start, [end]) VALUES ('02:00 9 Apr 2008', '02:00 2 Nov 2008'); 
INSERT INTO dst (start, [end]) VALUES ('02:00 8 Apr 2009', '02:00 1 Nov 2009'); 
INSERT INTO dst (start, [end]) VALUES ('02:00 14 Apr 2010', '02:00 7 Nov 2010'); 
INSERT INTO dst (start, [end]) VALUES ('02:00 13 Apr 2011', '02:00 6 Nov 2011'); 
INSERT INTO dst (start, [end]) VALUES ('02:00 11 Apr 2012', '02:00 4 Nov 2012'); 
INSERT INTO dst (start, [end]) VALUES ('02:00 10 Apr 2013', '02:00 3 Nov 2013'); 

Naturalmente potrebbe essere necessario un molto più di questo - lascerà fare quello come esercizio per il lettore :-)

Ok, diciamo che popolavano il sopra la tabella con l'intera gamma possibile e si dispone di data/orari nel campo dt della tabella test. Poi si può aderire alla tabella riportata sopra e fare le conversioni in questo modo:

-- Convert sample dates to PST offset with daylight saving where appropriate 
SELECT test.dt, 
     CAST(CONVERT(VARCHAR(23), test.dt, 126) + -- Convert to ISO8601 format 
      CASE WHEN dst.start IS NULL 
       THEN '-08:00' -- No record joined so not within DST period 
       ELSE '-07:00' -- DST record joined so is within DST period 
      END AS DateTimeOffset) AS dto 
FROM test 
LEFT JOIN dst -- Join on daylight savings table to find out whether DST applies 
ON test.dt >= dst.start 
AND test.dt <= dst.[end] 

Ecco un SQL fiddle demo.

2

SQL Server 2016 ha introdotto la sintassi T-SQL AT TIME ZONE per risolvere questo tipo di problemi.

Quindi, se si conosce il fuso orario dei dati, è possibile aggiungere l'offset utilizzando un semplice script alter e aggiornamento, come illustrato di seguito (ammesso che abbiate una tabella denominata MyTable avere una colonna datetime2 chiamato DateTimeColumn):

alter table MyTable 
    alter column DateTimeColumn datetimeoffset; 

update Mytable 
    set DateTimeColumn = convert(datetime2, DateTimeColumn) AT TIME ZONE 'Pacific Standard Time' 

L'ora legale (DST) viene considerata e non dovrebbero verificarsi perdite di dati.

(So che l'OP ha specificato SQL Server 2008 e la domanda è stata posta e ha risposto molto tempo fa, ma si spera che a tutti coloro che attualmente sono alle prese con lo stesso tipo di problema verrà data una risposta.)