datestyle忽略格式postgresql

时间:2017-07-26 19:25:36

标签: postgresql command-prompt psql

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

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

问题是,我无法更改csv文件中的数据,所以我必须找到一种导入这个错误日期的方法。

1 个答案:

答案 0 :(得分: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等文字一起使用,并会针对NULL2017-02-30等日期返回February 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
) ;

......你使用:

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(加载,转换,提取)等价物。