0

我有一张这样的桌子:

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

我正在尝试将数据导入表中,这样如果表中不存在file 和的组合,volume则应添加新行,否则如果存在现有行,则应更新该行,以便 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 子句的目的或用法?

4

2 回答 2

3

解决方案非常简单...

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

于 2017-05-08T06:24:15.787 回答
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 $$;

请注意,这种方法仅在没有删除表行的情况下才有效。

于 2017-05-08T06:26:23.600 回答