推薦閱讀
【PostgreSQL中Upsert如何區(qū)分執(zhí)行的是Insert還是Update?】
【PostgreSQL中Upsert實現(xiàn)最小化更新】
【PostgreSQL中實現(xiàn)Update前的備份騷操作】
眾所周知凑兰,PostgreSQL提供了Upsert的功能(具體是9.5版本之后提供的),這里的upsert并不是通過UPSERT
關鍵字來實現(xiàn)有則更新癌蚁,無則插入俐填,而是通過INSERT ... ON CONFLICT DO UPDATE ...的方式實現(xiàn),具體的功能說明請參考官方文檔:【傳送門】
這不是我們今天討論的重點松嘶,今天所討論的是PGSQL中批量插入的時候的UPSERT用法念恍。
首先我們假設有一個表aa犁功,分別三個字段:id衡未、a尸执、b
PGSQL批量插入
以下是兩種常見的基本插入操作:
-- 插入單條記錄的語句可以如下:
INSERT INTO aa VALUES (1,2,3);
-- 插入單條語句(指定某幾個字段)可以如下:
INSERT INTO aa (id,a,b) VALUES (1,2,3);
那么如果我們需要使用到批量插入呢:
-- 批量插入多條記錄
INSERT INTO aa VALUES (1,2,3),(2,3,4),(3,4,5);
當需要使用UPSERT時候,可以如下操作:
-- 插入或更新id為1的記錄
INSERT INTO aa VALUES (1,2,3) ON CONFLICT (id) DO UPDATE SET a=0,b=0;
那么問題來了缓醋,當需要用到批量UPSERT的時候該怎么做呢如失?如果按照下面的做法:
-- 批量操作更新或插入?
INSERT INTO aa VALUES (1,2,3),(2,3,4),(3,4,5) ON CONFLICT DO UPDATE SET a=0,b=0;
這樣會造成所有已經(jīng)存在的行的a和b字段都會被更新為0改衩,這顯然與我們的目的不符岖常。那么該怎么做呢?
這里需要用到PG中提供的一個特性:關鍵字EXCLUDED
葫督!在PG中提供了一個特殊的表EXCLUDED
,用來引用原來要插入的值板惑。(TIPS:如果你要往一個本身就叫做EXCLUDED的表中插入數(shù)據(jù)橄镜,這里記得給那個表起個別名來避免由于關鍵字沖突導致的不必要錯誤)
-- 批量插入或更新的正確操作:
INSERT INTO aa VALUES (1,2,3),(2,3,4),(3,4,5) ON CONFLICT DO UPDATE SET a=EXCLUDED.a,b=EXCLUDED.b;
若執(zhí)行前的表中數(shù)據(jù)如下:
id | a | b |
---|---|---|
1 | 0 | 0 |
2 | 1 | 1 |
則執(zhí)行上述語句后表中數(shù)據(jù)如下:
id | a | b |
---|---|---|
1 | 2 | 3 |
2 | 3 | 4 |
3 | 4 | 5 |
這樣一來,便實現(xiàn)了批量UPSERT的目的冯乘。當然洽胶,DO UPDATE ... WHERE xxx
也是可以的,這樣就可以限制更新條件了裆馒。
至于更多的UPSERT相關內容姊氓,請自行查閱資料哦。
補充
今天在開發(fā)中突然發(fā)現(xiàn)喷好,通過serial
或者sequence
創(chuàng)建的自增ID列翔横,在執(zhí)行Upsert
的時候也會增加,即使因為沖突導致執(zhí)行了UPDATE
操作梗搅,但是SEQUENCE
的值也會增加禾唁。具體如何解決沒有探究效览。