2017-05-08 58 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 $$; 

注意,这种方法适用仅如果没有表的行删除。