2017-07-26 99 views
0

我试图忽略csv文件,我上传通过命令行到PostgreSQL非法格式的日期:DATESTYLE忽略格式的PostgreSQL

Error: date/time field value out of range:"199999999" 

的问题是,我不能在CSV更改数据文件,所以我必须找到导入这个错误日期的方法。

回答

1

使用中间表(loaded_data)来存储您从CSV获得的数据。确保该表中的所有列都是text类型,以便PostgreSQL几乎可以接受(除非您的行的列数不正确)。

一旦你在该表中的所有数据,消毒所有列,这样,当它们的值是不正确的,你要么将它们设置为NULL,丢弃(DELETE它们)或设置这些列的默认值。你实际做的将取决于你的特定应用。

最简单的(尽管可能不是最快的)方式来清理您的数据是使用函数CAST您的文本到适当的类型,并处理异常如果输入格式不正确。对于date类型的情况下,可以使用以下功能:

-- Create a function to get good dates... and return NULL if they're not 
CREATE FUNCTION good_date(date_as_text text) 
    RETURNS DATE  /* This is the type of the returned data */ 
    IMMUTABLE STRICT /* If you pass a NULL, you'll get a NULL */ 
    LANGUAGE PLPGSQL /* Language used to define the function */ 
AS 
$$ 
BEGIN 
    RETURN CAST(date_as_text AS DATE) ; 
EXCEPTION WHEN OTHERS THEN /* If something is wrong... */ 
    RETURN NULL ; 
END 
$$ ; 

注意,这个函数的行为将取决于你的设置datestyle。但是,它始终与January 8, 1999之类的文本一起工作,并且将返回NULL以获得诸如2017-02-30February 30, 2017之类的日期。

您将执行good_integer函数的等效项。


让我们假设你有这样的输入数据:

CREATE TABLE loaded_data 
(
    some_id text, 
    some_date text 
) ; 

-- Let's assume this is the equivalent of loading the CSV... 
INSERT INTO loaded_data 
    (some_id, some_date) 
VALUES 
    (1, '20170101'), 
    (2, '19999999'), 
    (3, 'January 1, 1999'), 
    (4, 'February 29, 2001'), 
    (5, '20170230'); 

...这要存储下表中的信息:

CREATE TABLE destination_table 
( 
    id integer PRIMARY KEY, 
    a_date date 
) ; 

...你” d使用:

INSERT INTO destination_table 
    (id, a_date) 
SELECT 
    good_integer(some_id) AS id, good_date(some_date) AS a_date 
FROM 
    loaded_data ; 

而且你会得到:

SELECT * FROM destination_table; 
 
id | a_date  
-: | :--------- 
1 | 2017-01-01 
2 | null  
3 | 1999-01-01 
4 | null  
5 | null  

检查所有的设置在dbfiddle here


替代方案:用一些ETL工具],可以执行类似的功能。我介绍的场景在某种程度上是一个非常简单的LTE(加载,转换,提取)等效。