Postgres INSERT ON CONFLICT DO UPDATE vs INSERT或UPDATE

Shu*_*Tee 11 postgresql sql-update sql-insert

我有stock_price_alert3列的表.stock_price_idPRIMARY KEYFOREIGN KEY其他表.表定义如下:

create table stock_price_alert (
    stock_price_id integer references stock_price (id) on delete cascade not null,
    fall_below_alert boolean not null,
    rise_above_alert boolean not null,
    primary key (stock_price_id)
);
Run Code Online (Sandbox Code Playgroud)

我需要:

1)INSERT记录如果不存在

-- query 1
INSERT INTO stock_price_alert (stock_price_id, fall_below_alert, rise_above_alert)
VALUES (1, true, false);
Run Code Online (Sandbox Code Playgroud)

2)UPDATE记录是否存在

-- query 2
UPDATE stock_price_alert SET
    fall_below_alert = true,
    rise_above_alert = false
WHERE stock_price_id = 1;
Run Code Online (Sandbox Code Playgroud)

首先,我需要SELECTstock_price_alert表上发出查询,以决定是执行查询(1)还是(2).

Postgres支持INSERT INTO TABLE .... ON CONFLICT DO UPDATE ...:

-- query 3
INSERT INTO stock_price_alert (stock_price_id, fall_below_alert, rise_above_alert)
VALUES (1, true, false)
ON CONFLICT (stock_price_id) DO UPDATE SET
    fall_below_alert = EXCLUDED.fall_below_alert,
    rise_above_alert = EXCLUDED.rise_above_alert;
Run Code Online (Sandbox Code Playgroud)

而不是使用query(1)或(2),我总是可以使用query(3)?然后我不需要SELECT在之前发出查询,它有助于简化代码.

但我想知道,这是最好的做法?查询(3)会导致性能问题或不必要的副作用吗?谢谢.

Yon*_*tch 9

查询3是Postgres 9.5中引入的"UPSERT"(= UPDATE或INSERT)的Postgres语法.

文档:

ON CONFLICT DO UPDATE保证原子INSERTUPDATE结果; 如果没有独立错误,即使在高并发性下,也可以保证这两种结果中的一种.这也称为UPSERT" UPDATEINSERT".

这是您尝试实现的最佳实践.

  • 我意识到`INSERT ... ON CONFLICT DO UPDATE`,如果主键有自动增量`SERIAL`,那么`SERIAL`每次都会增加,无论是INSERT还是UPDATE.这在SERIAL中造成了差距,尽管不是什么大问题.但是对于这个表,主键不是"SERIAL",所以这里没有这样的缺点.我决定在这里只使用`query 3`.谢谢你的帮助,谢谢! (2认同)