我试图忽略我通过命令行上传到postgresql的csv文件中的非法格式化日期:
Error: date/time field value out of range:"199999999"
问题是,我无法更改csv文件中的数据,所以我必须找到一种导入这个错误日期的方法。
答案 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
等文字一起使用,并会针对NULL
或2017-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(加载,转换,提取)等价物。