2012-10-01 17 views
8

Devo importare i dati senza informazioni sul fuso orario (tuttavia, conosco il fuso orario specifico dei dati che voglio importare), ma ho bisogno del formato timestamp with time zone nel database. Una volta importato e impostato il tipo di data/ora su timestamp with time zone, Postgres supporrà automaticamente che i dati nella tabella provengano dal mio fuso orario e assegnino il mio fuso orario ad esso. Sfortunatamente i dati che voglio importare non provengono dal mio arco temporale, quindi non funziona.Modifica del fuso orario dei dati

Il database contiene anche dati con fusi orari diversi. Tuttavia, il fuso orario all'interno di una tabella è sempre lo stesso.

Ora, potrei impostare il fuso orario del database sul fuso orario dei dati che voglio importare prima di importare i dati (usando il comando SET time zone) e cambiarlo al mio fuso orario una volta che l'importazione è stata completata, e Sono abbastanza sicuro che i dati memorizzati non saranno influenzati dalla modifica del fuso orario del database. Ma questo sembra essere un approccio piuttosto sporco e potrebbe causare problemi in seguito.

Mi chiedo se esiste un modo più elegante per specificare il fuso orario per l'importazione senza avere i dati del fuso orario nei dati stessi?

Inoltre, non ho trovato un modo per modificare le informazioni sul fuso orario dopo l'importazione. C'è un modo per non convertire, ma semplicemente per modificare il fuso orario per un'intera tabella, supponendo che l'intera tabella abbia lo stesso offset di fuso orario (ad esempio se è stata assegnata una errata all'immissione/importazione dei dati)?

Edit:
sono riuscito a specificare un fuso orario al momento dell'importazione, l'intero comando di essere:

set session time zone 'UTC'; 
COPY tbl FROM 'c:\Users\Public\Downloads\test.csv' DELIMITERS ',' CSV; 
set session time zone 'CET'; 

I dati poi viene importati utilizzando il fuso orario della sessione. Presumo che questo non abbia alcun effetto su altre query sul database allo stesso tempo da altre connessioni?

Edit 2:
ho scoperto come cambiare il fuso orario di una tabella in seguito:
PostgreSQL update time zone offset

Suppongo che sia più elegante di cambiare il fuso orario del tavolo dopo l'importazione quindi di utilizzare la sessione per modificare il fuso orario locale temporaneo. Supponendo che l'intero tavolo abbia lo stesso fuso orario, ovviamente.

Così il codice sarebbe ora qualcosa lungo la linea del:

COPY tbl FROM 'c:\Users\Public\Downloads\test.csv' DELIMITERS ',' CSV; 
UPDATE tbl SET <tstz_field> = <tstz_field> AT TIME ZONE '<correct_time_zone>'; 
+0

Come stai eseguendo l'importazione? non puoi assegnare il fuso orario durante l'importazione? – ertx

+0

Grazie per il suggerimento, ho aggiornato il mio post ma non sono sicuro del tipo di effetto che il fuso orario della sessione ha sugli altri processi all'interno del database al momento dell'esecuzione? – harbun

risposta

11

È molto più efficiente per impostare il fuso orario per la sessione di importazione che per aggiornare i valori in seguito.

Ho l'impressione che si pensi al fuso orario come un'impostazione che si applica a valori altrimenti immutati nelle tabelle. Ma non è affatto così. Pensalo come un modificatore di input/output. I valori effettivi timestamp (con o senza fuso orario) sono sempre memorizzati come timestamp UTC internamente (numero di secondi dal '2000-01-01 00:00').Un sacco maggiori dettagli:

Il UPDATE nel secondo esempio raddoppia la dimensione della tabella, come ogni singola riga viene invalidata e una nuova versione ha aggiunto (che è come UPDATE opere con MVCC a Postgres). Oltre all'operazione costosa, lo VACUUM dovrà svolgere più lavoro in seguito per ripulire il tavolo. Molto inefficace.

È perfettamente sicuro a SET il fuso orario locale per la sessione. Ciò non influisce in alcun modo sulle operazioni concorrenti. Btw., SET SESSION è lo stesso del semplice SET perché il valore predefinito è SESSION.

Se si vuole essere assolutamente sicuri, è possibile limitare l'impostazione al corrente dell'operazione con SET LOCAL. Cito i manuali here

Gli effetti di SET LOCAL durano solo fino alla fine della corrente transazione, sia impegnato o meno. Un caso particolare è SET seguita da SET LOCAL all'interno di una singola transazione: il valore SET LOCAL sarà visto fino alla fine della transazione, ma in seguito (se l'operazione è impegnata ) il valore SET avrà effetto.

mettere insieme:

BEGIN; 
SET LOCAL timezone = 'UTC'; 
COPY tabledata FROM 'c:\Users\Public\Downloads\test.csv' DELIMITERS ',' CSV; 
COMMIT; 

Check:

SHOW timezone; 
+0

** Esattamente ** quello che dovevo sapere, ottima spiegazione. Danke Erwin. :) – harbun

+0

@harbun: Bitteschön. :) –