22

我有一张桌子

CREATE TABLE foo
(
    f0 int,
    time_stamp timestamp,
    CONSTRAINT foo_pk PRIMARY KEY (f0)
)

我需要大量写入此表,因此性能是关键。有时,我会写一条具有现有值的记录,f0并将其更新time_stamp为当前时间。为此,我使用了一个ON CONFLICT..DO UPDATE子句。

问题是我需要知道是INSERT发生了还是UPDATE.

我虽然使用第二is_update列。插入时,插入false

`ON CONFLICT .. DO UPDATE set is_update=true`

然后用RETURNING is_update得到我想要的。问题在于引入了与数据本身无关的附加列。

4

2 回答 2

4

使用两列作为时间戳是常见的做法。一creation_timestamp列将在插入时设置一次。虽然 anupdate_timestamp会将最后一次覆盖更新的时间戳保留到该记录。

在每个“upsert”上,您可以检查是否尚未设置 update_timestamp。

INSERT INTO foo (f0, creation_timestamp) VALUES (1, NOW())
ON CONFLICT (f0)
DO UPDATE
SET f0=EXCLUDED.f0, update_timestamp=NOW()
RETURNING update_timestamp IS NULL
于 2021-05-06T20:17:03.950 回答
2

您可以在 foo 表上创建触发器函数。然后insert使用 TG_OP 保留字捕获操作,如果 key 存在则更新,否则插入新行。尚未用大行测试:)

1.创建程序:

CREATE OR REPLACE FUNCTION public.f0_update_on_duplicate()
 RETURNS trigger
 LANGUAGE plpgsql
AS $function$
declare _exists boolean;
begin
  if TG_OP = 'INSERT' then
    select exists(select true from foo where f0 = NEW.f0) into _exists;
    raise notice '%', _exists;
    if _exists = TRUE then
      update foo set time_stamp = NEW.time_stamp where f0 = NEW.f0;
      return NULL;
    else
      return NEW;
    end if;
  end if;
end
$function$;

2.将过程附加到 foo 表:

CREATE TRIGGER update_on_duplicate 
BEFORE INSERT ON foo FOR EACH ROW EXECUTE PROCEDURE
f0_update_on_duplicate();

3.测试插入。这应该用新的 time_stamp 更新 f0 (假设 f0 = 5 已经存在于 foo 表中):

INSERT INTO foo (f0, time_stamp) VALUES ( 5, now() );

于 2017-08-30T04:50:54.107 回答