我正在尝试编写查询以将值插入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文件中的日期格式 有没有办法将日期字符串转换为时间戳,具体取决于其实际格式?
答案 0 :(得分:15)
您需要将日期样式设置为“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设置和相关行为很古老,所以应该可以正常工作)
答案 1 :(得分:7)
您可以通过以下步骤解决问题:
创建一个空的临时表,其结构与目标表相同:
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
进入目标表,具体取决于列的实际内容:
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
答案 2 :(得分:1)
我同意Erwin,但我会尝试创建可以将各种日期字符串转换为date
的数据库函数(PL / pgSQL,PL / Python或其他语言)。在Erwins的回答中,您可以看到WHEN ... THEN
,您可以使用它。这样的功能将更容易测试和维护。