Как преобразовать строки даты в метку времени, не зная формат даты - PullRequest
13 голосов
/ 15 ноября 2011

Я пытаюсь написать запрос для вставки значения в поле типа 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.
Можно ли преобразовать строки даты в метку времени в зависимости от ее фактического формата?

Ответы [ 3 ]

15 голосов
/ 15 ноября 2011

Вам необходимо установить свой стиль дат на «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 и связанное с ним поведение устарели, поэтому должно работать нормально)

7 голосов
/ 15 ноября 2011

Вы можете обойти проблему с помощью этих шагов:

  1. Создать пустую временную таблицу с той же структурой, что и у целевой таблицы:

    CREATE TEMP TABLE tmp AS SELECT * FROM real_tbl LIMIT 0;
    
  2. Измените тип проблемного столбца на текст :

    ALTER TABLE tmp ALTER COLUMN str_date TYPE text;
    
  3. Импорт данных во временную таблицу. Теперь должно нормально работать:

    COPY tmp FROM '/path/to/my/file.txt';
    
  4. INSERT в целевую таблицу в зависимости от фактического содержания столбца:

    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
    
1 голос
/ 15 ноября 2011

Я согласен с Эрвином, но я бы попробовал создать функцию базы данных (PL / pgSQL, PL / Python или другой язык), которая может конвертировать различные строки даты в date. В ответе Эрвинса вы видите WHEN ... THEN и можете его использовать. Такую функцию будет проще тестировать и поддерживать.

...