2017-05-08 62 views
0

我有這樣的一個表:PostgreSQL的INSERT ... ON衝突......哪裏都不觸發

CREATE TABLE import_files (
    id   SERIAL PRIMARY KEY, 
    file  TEXT NOT NULL, 
    volume  TEXT NOT NULL, 
    lastimport DATE DEFAULT CURRENT_DATE, 
    UNIQUE (file,volume) 
) 

我試圖將數據導入到表中,這樣如果filevolume組合在表中不存在的情況下,應添加新行,否則如果存在行,則應更新該行,以便 lastimport是今天的日期。

但是,我不想做任何更新,如果該行已經是今天的日期( 相同的行可能會提交一天多次)。

我試圖使用PostgreSQL 9.6的這個新ON CONFLICT子句,如下所示:

INSERT INTO import_files(file,volume) 
VALUES('MyFile1', 'VolA') 
ON CONFLICT (file,volume) DO 
    UPDATE SET lastimport = CURRENT_DATE 
WHERE EXCLUDED.lastimport < CURRENT_DATE 
RETURNING id 

,但它似乎並沒有爲我工作。最初的導入工作正常,但對於 更新情況下,它似乎並沒有更新即使在WHERE子句是真實的:

t1=> select * from import_files; 
id | file | volume | lastimport 
----+---------+--------+------------ 
    1 | MyFile1 | VolA | 2017-05-07 
(1 row) 

t1=>  INSERT INTO import_files(file,volume) 
    VALUES('MyFile1', 'VolA') 
    ON CONFLICT (file,volume) DO 
     UPDATE SET lastimport = CURRENT_DATE 
    WHERE EXCLUDED.lastimport < CURRENT_DATE 
    RETURNING id 
; 
id 
---- 
(0 rows) 

INSERT 0 0 

由於今天是2017年5月8日我本來預計要更新該行。

我是否誤解了在此上下文中WHERE子句的用途或用法?

回答

2

的解決方案是令人尷尬的簡單...

EXCLUDED表包含的行最初提出的插入,而不是正在更新當前行。我沒有爲lastimport指定一個值,所以它將填充默認值 - 在這種情況下,這是CURRENT_DATE,所以where子句永遠不會是真的。

相反,我應該一直在使用這樣的:

t1=> INSERT INTO import_files(file,volume) 
    VALUES('MyFile1', 'VolA') 
    ON CONFLICT (file,volume) DO 
     UPDATE SET lastimport = CURRENT_DATE 
    WHERE import_files.lastimport < CURRENT_DATE 
    RETURNING id 
; 
id 
---- 
    1 
(1 row) 

INSERT 0 1 

where子句應該已經與import_files.lastimport,而不是與EXCLUDED.lastimport提議的數值參考當前行值。

1

你可以使用不同的方法,對PostgreSQL的以前版本的作品:

do $$ 
begin 
    insert into import_files (file,volume) values('MyFile1', 'VolA'); 
exception when unique_violation then 
    update import_files 
    set lastimport = current_date 
    where file = 'MyFile1' and volume = 'VolA' and lastimport < current_date 
end $$; 

注意,這種方法適用僅如果沒有表的行刪除。