9

タイム ゾーン情報を含まないデータをインポートする必要があります (ただし、インポートするデータの特定のタイム ゾーンはわかっています) がtimestamp with time zone、データベースにはその形式が必要です。インポートしてタイムスタンプ データ型を に設定するとtimestamp with time zone、Postgres はテーブル内のデータが自分のタイム ゾーンからのものであると自動的に想定し、それに自分のタイム ゾーンを割り当てます。残念ながら、インポートしたいデータは私の時間枠のものではないため、これは機能しません。

データベースには、異なるタイム ゾーンのデータも含まれています。ただし、1 つのテーブル内のタイム ゾーンは常に同じです。

これで、データベースのタイム ゾーンを、データをインポートする前に (SET time zoneコマンドを使用して) インポートするデータのタイム ゾーンに設定し、インポートが完了したら自分のタイム ゾーンに戻すことができました。保存されたデータは、データベースのタイム ゾーンの変更の影響を受けません。しかし、これはかなり汚いアプローチのようで、後で問題を引き起こす可能性があります。

データ自体にタイム ゾーン データを含めずに、インポートのタイム ゾーンを指定するより洗練された方法があるのだろうか?

また、インポート後にタイム ゾーン情報を編集する方法が見つかりませんでした。テーブル全体に同じタイム ゾーン オフセットがあると仮定して (つまり、データ入力/インポート時に間違ったタイム ゾーンが割り当てられた場合)、テーブル全体のタイム ゾーンを変換せずに編集する方法はありますか?

編集:
インポート時にタイムゾーンを指定できました。コマンド全体は次のとおりです。

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

その後、データはセッションのタイム ゾーンを使用してインポートされます。これは、他の接続から同時にデータベース上の他のクエリに影響を与えないと思いますか?

編集2:
後でテーブルのタイムゾーンを変更する方法を見つけました:
PostgreSQL update time zone offset

インポート後にテーブルのタイムゾーンを変更してから、セッションを使用してローカルタイムゾーンを一時的に変更する方がエレガントだと思います。もちろん、テーブル全体のタイムゾーンが同じであると仮定します。

したがって、コードは次のようなものになります。

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

1 に答える 1

12

後で値を更新するよりも、インポートセッションのタイムゾーンを設定する方がはるかに効率的です。

タイムゾーンは、テーブル内の変更されていない値に適用される設定のように考えているように感じます。しかし、それはまったくそうではありません。これを入力/出力修飾子と考えてください。実際のtimestamp値(タイムゾーンの有無にかかわらず)は、常にUTCタイムスタンプとして内部的に保存されます(からの秒数'2000-01-01 00:00')。詳細:

UPDATE2番目の例では、すべての行が無効になり、新しいバージョンが追加されるため、テーブルのサイズが2倍になります(これがPostgresのMVCCUPDATEで機能する方法です)。費用のかかる操作に加えて、テーブルの肥大化をクリーンアップするために、後でさらに作業を行う必要があります。非常に非効率的です。VACUUM

セッションのローカルタイムゾーンに対して完全に安全です。SETこれは、並行操作にはまったく影響しません。ところで、とにかくデフォルトであるためSET SESSION、プレーンと同じです。SETSESSION

絶対に確認したい場合は、設定を現在のトランザクションに制限できますSET LOCALここでマニュアルを引用します

効果はSET LOCAL、コミットされているかどうかに関係なく、現在のトランザクションが終了するまでのみ持続します。特別な場合は、単一のトランザクション内でSET続きます。値はトランザクションの終了まで表示されますが、その後(トランザクションがコミットされている場合)、値が有効になります。SET LOCALSET LOCALSET

まとめる:

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

小切手:

SHOW timezone;
于 2012-10-01T18:47:33.060 に答える