timestamp with no timezone data
タイプのフィールドに値を挿入するクエリを作成しようとしています。値はCSVファイルから取得されます。
私が使用しているバージョンはPostgreSQL 8.1.21です。
CSVファイルのアップロードはクライアントによって行われ、日付列があります。日付は'28-Sep-13'
の形式で表示されることも、'28/09/2013'
の形式で表示されることもあります。
文字列をタイムスタンプにキャストするために次を使用しようとしました:str_date::timestamp
。
これは、str_date
が'28-Sep-13'
のようなものであれば正常に機能しますが、このエラーが発生したときに、受信日付の形式が'28/09/2013'
の場合は機能しません。
ERROR: date/time field value out of range: "28/09/2013" HINT: Perhaps you need a different "datestyle" setting
基本的に、クライアントはアップロードされたCSVファイルの日付形式を変更し続けます。
実際の形式に応じて日付文字列をタイムスタンプに変換する方法はありますか?
日付スタイルを「ISO、DMY」に設定する必要があります。デフォルトでは「ISO、MDY」に設定されており、サンプルが失敗します。
> show datestyle;
DateStyle
-----------
ISO, MDY
(1 row)
> select '28-Sep-13'::date;
date
------------
2013-09-28
(1 row)
> select '28/09/2013'::date;
ERROR: date/time field value out of range: "28/09/2013"
LINE 1: select '28/09/2013'::date;
^
HINT: Perhaps you need a different "datestyle" setting.
> set datestyle = 'ISO, DMY';
SET
> select '28-Sep-13'::date;
date
------------
2013-09-28
(1 row)
> select '28/09/2013'::date;
date
------------
2013-09-28
(1 row)
(PostgreSQL 9.1で行われた例ですが、DateStyleの設定とそれに関連する動作は古くからあるため、正常に動作するはずです)
次の手順で問題を回避できます。
ターゲットテーブルと同じ構造で空の一時テーブルを作成します。
CREATE TEMP TABLE tmp AS SELECT * FROM real_tbl LIMIT 0;
問題のある列のtypeをtextに変更します。
ALTER TABLE tmp ALTER COLUMN str_date TYPE text;
インポート一時テーブルへのデータ。今はうまくいくはずです:
COPY tmp FROM '/path/to/my/file.txt';
INSERT
into target table列の実際の内容に応じて異なります:
INSERT INTO real_tbl (col1, col2, col3, date_col)
SELECT col1, col2, col3
, CASE WHEN str_date ~~ '%/%'
THEN to_date(str_date, 'DD/MM/YYYY')
WHEN str_date ~~ '%-%'
THEN to_date(str_date, 'DD-Mon-YYYY')
-- more cases?
ELSE ???
END AS date_col
FROM tmp;
-- DROP TABLE tmp; -- optional; dropped at end of session automatically
Erwinに同意しますが、さまざまな日付文字列をdate
に変換できるデータベース関数(PL/pgSQL、PL/Pythonまたはその他の言語)を作成してみます。アーウィンズの回答では、WHEN ... THEN
そしてあなたはそれを使うことができます。このような機能は、テストと保守が容易になります。