我怎样才能在 Postgres 9.5 中做一些更新插入
How can I do some kind of upsert within Postgres 9.5
我有一个简单的table:
NAME | TIMESTAMP | AMOUNT
--------------------------
Name1 | 123 | 1
Name2 | 123 | 15
Name3 | 124 | 3
Name4 | 125 | 1
等等。
现在我得到了一个新记录。如果名称和时间戳相等,我希望数量增加新记录的数量,否则应该插入新记录。
类似于:
INSERT INTO test.data (NAME, TIMESTAMP, AMOUNT) values ('Name1', 123, 4)
IF not EXIST; OTHERWISE UPDATE test.data set AMOUNT + NEWAMOUNT where TIMESTAMP = oldTimestamp and NAME = oldName
这是否可以通过使用 Postgres 9.5 的一个简单 sql 查询以某种方式实现?
谢谢
使用新的 on conflict
子句:
INSERT INTO test.data (NAME, TIMESTAMP, AMOUNT)
values ('Name1', 123, 4)
on conflict (name, timestamp)
do update
set AMOUNT + excluded.NEWAMOUNT
这要求您在 (name, timestamp)
上定义了唯一约束(或索引)
如果您不想让 (name, timestamp)
独一无二,您 可以 使用可写的 CTE:
with new_values (name, timestamp, amount) as (
values ('Name1', 123, 4)
), changed as (
update data
set amount = amount + t.amount
from new_values nv
where data.name = nv.name
and data.timestamp = nv.timestamp
returning *
)
insert into data (name, timestamp, amount)
select name, timestamp, amount
from new_values
where not exists (select 1 from changed);
请注意(与 on conflict
解决方案不同)这对并发更新不安全,并且您可能有竞争条件
with t as (
update test.data set
AMOUNT = AMOUNT + 4
where
NAME = 'Name1' and TIMESTAMP = 123
returning
*) -- In the t we have list of updated rows (if any)
insert into test.data(NAME, TIMESTAMP, AMOUMT)
select 'Name1', 123, 4
where not exists (select * from t); -- Insert new row in rows was not updated
我有一个简单的table:
NAME | TIMESTAMP | AMOUNT
--------------------------
Name1 | 123 | 1
Name2 | 123 | 15
Name3 | 124 | 3
Name4 | 125 | 1
等等。 现在我得到了一个新记录。如果名称和时间戳相等,我希望数量增加新记录的数量,否则应该插入新记录。
类似于:
INSERT INTO test.data (NAME, TIMESTAMP, AMOUNT) values ('Name1', 123, 4)
IF not EXIST; OTHERWISE UPDATE test.data set AMOUNT + NEWAMOUNT where TIMESTAMP = oldTimestamp and NAME = oldName
这是否可以通过使用 Postgres 9.5 的一个简单 sql 查询以某种方式实现?
谢谢
使用新的 on conflict
子句:
INSERT INTO test.data (NAME, TIMESTAMP, AMOUNT)
values ('Name1', 123, 4)
on conflict (name, timestamp)
do update
set AMOUNT + excluded.NEWAMOUNT
这要求您在 (name, timestamp)
如果您不想让 (name, timestamp)
独一无二,您 可以 使用可写的 CTE:
with new_values (name, timestamp, amount) as (
values ('Name1', 123, 4)
), changed as (
update data
set amount = amount + t.amount
from new_values nv
where data.name = nv.name
and data.timestamp = nv.timestamp
returning *
)
insert into data (name, timestamp, amount)
select name, timestamp, amount
from new_values
where not exists (select 1 from changed);
请注意(与 on conflict
解决方案不同)这对并发更新不安全,并且您可能有竞争条件
with t as (
update test.data set
AMOUNT = AMOUNT + 4
where
NAME = 'Name1' and TIMESTAMP = 123
returning
*) -- In the t we have list of updated rows (if any)
insert into test.data(NAME, TIMESTAMP, AMOUMT)
select 'Name1', 123, 4
where not exists (select * from t); -- Insert new row in rows was not updated