如何添加与ON CONFLICT做比较的比较

问题描述

我需要检查表中是否有当前用户当前进行的任何操作。 通常,我以这种方式比较时间:timestamp > CURRENT_TIMESTAMP::date

请您提供帮助,如何在ON CONFLICT()做UDPATE的INSERT中执行此操作?

        INSERT INTO table (login,smth,timestamp)
          VALUES ('username','smth',CURRENT_TIMESTAMP)
        ON CONFLICT (login,timestamp) DO UPDATE
          SET smth = 'smth'
              timestamp = CURRENT_TIMESTAMP

这里将与时间戳进行精确比较,但我需要检查是否是今天的时间戳,例如:timestamp > CURRENT_TIMESTAMP::date

谢谢!

解决方法

如果要存储时间戳,但对日期有唯一的约束,则可以使用计算列在最新版本的Postgres中轻松地做到这一点。这需要在表中添加一个新列,即日期:

create table t (
     login text,smth text,ts timestamp,ts_date date generated always as (ts::date) stored
);

然后创建一个唯一约束:

create unique index unq_t_login_timestamp on t(login,ts_date);

现在您可以使用on conflict

INSERT INTO t (login,smth,ts)
    VALUES ('username','smth',CURRENT_TIMESTAMP)
    ON CONFLICT (login,ts_date) DO UPDATE
          SET smth = 'smth',ts = CURRENT_TIMESTAMP;

Here是db 小提琴中的代码。

编辑:

最好避开计算列并仅使用:

create unique index unq_t_login_timestamp on t(login,(timestamp::date));
,

如果可以使用CTE,请参见here

如果您有任何疑问,查询如下: (但是,我不清楚“时间戳> CURRENT_TIMESTAMP :: date”是什么意思。)

with
"data"("w_login","w_smth","w_timestamp") as (
  select 'username2'::text,'smth'::text,CURRENT_TIMESTAMP
),"update" as (
  update "table" set ("smth","timestamp")=("w_smth","w_timestamp") from "data"
  where "login"="w_login" and "w_timestamp">CURRENT_TIMESTAMP::date
  returning *
)
insert into "table"
select * from "data"
where not exists (select * from "update");

DB Fiddle