2012-10-01 18 views
8

Ich muss importieren Daten ohne Zeitzone Informationen drin (aber ich kenne die spezifische Zeitzone der Daten, die ich importieren möchte), aber ich brauche das Format timestamp with time zone in der Datenbank. Sobald ich es importiere und den Zeitstempeldatentyp auf timestamp with time zone setze, nimmt Postgres automatisch an, dass die Daten in der Tabelle aus meiner Zeitzone stammen und weise mir meine Zeitzone zu. Leider sind die Daten, die ich importieren möchte, nicht von meinem Zeitrahmen, also funktioniert das nicht.Ändern der Zeitzone Wert der Daten

Die Datenbank enthält auch Daten mit unterschiedlichen Zeitzonen. Die Zeitzone innerhalb einer Tabelle ist jedoch immer gleich.

Jetzt konnte ich die Zeitzone der Datenbank auf die Zeitzone der Daten einstellen, die ich importieren möchte, bevor ich die Daten importiere (mit dem Befehl SET time zone) und nach dem Import zurück in meine Zeitzone ändere Ich bin mir ziemlich sicher, dass bereits gespeicherte Daten nicht von der Zeitzonenänderung der Datenbank betroffen sind. Aber das scheint ein ziemlich dreckiger Ansatz zu sein und kann später Probleme verursachen.

Ich frage mich, ob es eine elegantere Möglichkeit gibt, die Zeitzone für den Import anzugeben, ohne die Zeitzonendaten in den Daten selbst zu haben?

Auch habe ich keine Möglichkeit gefunden, Zeitzone Informationen nach dem Import zu bearbeiten. Gibt es eine Möglichkeit, die Zeitzone für eine ganze Tabelle nicht zu konvertieren, sondern nur die Zeitzone für eine ganze Tabelle zu bearbeiten, vorausgesetzt, die gesamte Tabelle hat denselben Zeitzonen-Offset (d. H. Wenn bei der Dateneingabe/-import ein falscher Wert zugewiesen wurde)?

Edit:
ich es geschafft, eine Zeitzone nach Import angeben, wird der gesamte Befehl Wesen:

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

Die Daten werden dann importiert wird die Sitzung Zeitzone verwenden. Ich nehme an, das hat keine Auswirkungen auf andere Abfragen in der Datenbank gleichzeitig von anderen Verbindungen?

Edit 2:
ich herausgefunden, wie die Zeitzone einer Tabelle zu ändern, danach:
PostgreSQL update time zone offset

Ich nehme an, es eleganter ist es, die Zeitzone der Tabelle nach dem Import zu ändern dann Sitzung zu verwenden um die lokale Zeitzone vorübergehend zu ändern. Angenommen, die ganze Tabelle hat natürlich die gleiche Zeitzone.

So ist der Code wäre jetzt etwas entlang der Linie:

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

Wie ausführen Sie importieren? Können Sie die Zeitzone beim Importieren nicht zuweisen? – ertx

+0

Danke für den Tipp, ich habe meinen Beitrag aktualisiert, aber ich bin mir nicht sicher, welche Art von Effekt Einstellung Sitzung Zeitzone auf andere Prozesse in der Datenbank zum Zeitpunkt der Ausführung hat? – harbun

Antwort

11

Es ist viele effiziente, die Zeitzone für Ihre Import-Sitzung zu setzen, als später die Werte zu aktualisieren.

Ich habe den Eindruck, dass Sie an die Zeitzone wie eine Einstellung denken, die für ansonsten unveränderte Werte in den Tabellen gilt. Aber so ist es überhaupt nicht. Stellen Sie es sich als Eingabe/Ausgabe-Modifikator vor. Aktuelle timestamp Werte (mit oder ohne Zeitzone) sind immer intern gespeichert als Zeitstempel UTC (Anzahl der Sekunden seit '2000-01-01 00:00').Viel mehr Details:

Die UPDATE in Ihrem zweiten Beispiel verdoppelt sich die Größe der Tabelle, da jede einzelne Zeile für ungültig erklärt wird und eine neue Version hinzugefügt (das ist, wie UPDATE Arbeiten mit MVCC in Postgres). Zusätzlich zu der teuren Operation muss VACUUM später mehr Arbeit erledigen, um den Tabellen-Bloat zu bereinigen. Sehr ineffizient.

Es ist perfekt sicher bis SET die lokale Zeitzone für die Sitzung. Dies wirkt sich nicht auf gleichzeitige Vorgänge aus. Btw., SET SESSION ist das gleiche wie Plain SET, weil SESSION sowieso die Standardeinstellung ist.

Wenn Sie absolut sicher sein wollen, können Sie die Einstellung auf die aktuelle Transaktion mit SET LOCAL begrenzen. Ich zitiere die manuellen here

Die Auswirkungen von SET LOCAL zuletzt nur bis zum Ende der laufenden Transaktion, ob begangen oder nicht. Ein Sonderfall ist SET gefolgt von SET LOCAL innerhalb einer einzigen Transaktion: der SET LOCAL Wert bis zum Ende der Transaktion zu sehen sein wird, aber danach (wenn die Transaktion festgeschrieben) der SET Wert wirksam werden.

zusammen:

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

Check:

SHOW timezone; 
+0

** Genau ** was ich wissen musste, großartige Erklärung. Danke Erwin. :) – harbun

+0

@harbun: Bitteschön. :) –