web-dev-qa-db-ja.com

日付形式を知らずに日付文字列をタイムスタンプに変換する方法

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ファイルの日付形式を変更し続けます。
実際の形式に応じて日付文字列をタイムスタンプに変換する方法はありますか?

13
Shiver

日付スタイルを「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の設定とそれに関連する動作は古くからあるため、正常に動作するはずです)

15
Matthew Wood

次の手順で問題を回避できます。

  1. ターゲットテーブルと同じ構造で空の一時テーブルを作成します。

    CREATE TEMP TABLE tmp AS SELECT * FROM real_tbl LIMIT 0;
    
  2. 問題のある列のtypetextに変更します。

    ALTER TABLE tmp ALTER COLUMN str_date TYPE text;
    
  3. インポート一時テーブルへのデータ。今はうまくいくはずです:

    COPY tmp FROM '/path/to/my/file.txt';
    
  4. 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
    
7

Erwinに同意しますが、さまざまな日付文字列をdateに変換できるデータベース関数(PL/pgSQL、PL/Pythonまたはその他の言語)を作成してみます。アーウィンズの回答では、WHEN ... THENそしてあなたはそれを使うことができます。このような機能は、テストと保守が容易になります。

1
Michał Niklas