问题描述
我需要检查表中是否有当前用户当前进行的任何操作。
通常,我以这种方式比较时间: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");