Postgresql 如何在不知道日期格式的情况下将日期字符串转换为时间戳

Postgresql 如何在不知道日期格式的情况下将日期字符串转换为时间戳,postgresql,timestamp,date-format,bulk-load,postgresql-copy,Postgresql,Timestamp,Date Format,Bulk Load,Postgresql Copy,我正在尝试编写一个查询,以便在没有时区数据的时间戳中插入一个值。该值来自CSV文件 我正在使用的版本是PostgreSQL 8.1.21 CSV文件上载由客户端完成,并且有一个日期列。日期有时为2013年9月28日,有时为2013年9月28日 我尝试使用以下方法将字符串转换为时间戳: stru date::timestamp 如果stru date类似于'28-Sep-13',则此功能可以正常工作,但如果传入日期的格式为'28/09/2013',则此功能不起作用,当出现此错误时: 基本上,客户端

我正在尝试编写一个查询,以便在没有时区数据的
时间戳中插入一个值。该值来自CSV文件

我正在使用的版本是PostgreSQL 8.1.21

CSV文件上载由客户端完成,并且有一个日期列。日期有时为2013年9月28日,有时为2013年9月28日

我尝试使用以下方法将字符串转换为时间戳:
stru date::timestamp

如果
stru date
类似于
'28-Sep-13'
,则此功能可以正常工作,但如果传入日期的格式为
'28/09/2013'
,则此功能不起作用,当出现此错误时:

基本上,客户端会不断更改上载的CSV文件中的日期格式。

有没有办法根据日期字符串的实际格式将其转换为时间戳?

您可以通过以下步骤避免此问题:

  • 创建一个空的临时表,其结构与目标表相同:

    CREATE TEMP TABLE tmp AS SELECT * FROM real_tbl LIMIT 0;
    
  • 将有问题列的类型更改为文本

    ALTER TABLE tmp ALTER COLUMN str_date TYPE text;
    
  • 将数据导入临时表。现在应该可以正常工作了:

    COPY tmp FROM '/path/to/my/file.txt';
    
  • 根据列的实际内容将
    插入目标表

    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的观点,但我会尝试创建数据库函数(PL/pgSQL、PL/Python或其他语言),该函数可以将各种日期字符串转换为
    date
    。在欧文回答中,您可以看到
    当。。。然后
    ,您就可以使用它了。这样的功能将更易于测试和维护。

    您需要将日期样式设置为“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中所做的例子,但数据体裁设置和相关行为是古老的,所以应该工作精细)

    首先:考虑升级。太过时了。你们以我的生日为例真是太好了;-)谢谢马修的帮助。我在查询中添加了set-datestyle='ISO,DMY',问题就解决了。很高兴听到它解决了这个问题。如果您能将答案标记为已接受,我们将不胜感激!
    > 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)