postgres 關於insert or update優化

執行批量的 insert

INSERT INTO users (id, level)
VALUES (1, 3), (2, 1)
ON CONFLICT (id) DO UPDATE
SET level = excluded.level;

我們看到已存在行(id=1) 的 level 更新爲新的值 3, 並且插入新行。

這裏注意到我們用到一個關鍵字 excluded 用於引用 INSERT 語句中 VALUES 提供的值,相應的表名 users 用於引用表中原有的值。

基於 unnest 的 upsert 操作

前面仍然是寫作此文的意外收穫,實際上想要總結的是 unnest 關鍵字在批量操作中的作用。下面來進行演示

insert into testunnest(id, col1, col2) 
 values (unnest(array[1,2]), unnest(array[30,40]), unnest(array['val1', 'val2']));

換成成 unnest(array[..]) 的形式有一種行轉列的行爲。

用 unnest 加上 unsert 再執行一次插入

insert into testunnest(id, col1, col2)
 values (unnest(array[2,3]), unnest(array[80,90]), unnest(array['valupdated', 'val3']))
 on conflict (id) do update
 set col1 = excluded.col1, col2 = excluded.col2

unnest 與 JDBC 操作

insert into users values (?, ?) on conflict.... 的 SQL 語句的單條記錄或批量操作(addBatch(), executeBatch()) 就不多說了,主要看下用 JDBC 怎麼對 unnest 進行賦值操作

PreparedStatement pstmt = conn.prepareStatement(
 "INSERT INTO testunnest(id, col1, col2) " +
  " VALUES (unnest(?), unnest(?), unnest(?))" +
  " ON CONFLICT (id) DO UPDATE" +
  " SET col1 = excluded.col1, col2 = excluded.col2"
);
 
pstmt.setArray(1, conn.createArrayOf("int", new Integer[]{2, 3}));
pstmt.setArray(2, conn.createArrayOf(JDBCType.INTEGER.getName(), new Integer[]{80, 90}));
pstmt.setArray(3, conn.createArrayOf("varchar", new String[]{"val1", "val2"}));
 
int update = pstmt.executeUpdate();
System.out.println(update); //影響的記錄數是 2

點位符要用 unnest(?),設置參數時要用 setArray(), 參數用 conn.createArrayOf(type, array) 來指定。需要指明數組中的元素類型,這麼普通的 setInt(), setString() 是一個意思。

用不着轉換爲 PostgreSQL 特定的 PreparedStatement 來操作,用 JDBC 通用的 PreparedStatement 接口就能支持對數組類型的賦值

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章