2017-07-26 107 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(加載,轉換,提取)等效。