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)