前言
就在 2019 年 1 月份微软收购了 PostgreSQL 数据库的初创公司 CitusData, 在云数据库方面可以增强与 AWS 的竟争。AWS 的 RDS 两大开源数据库就是 MySQL(Aurora 和 MariaDB 是它的变种) 和 PostgreSQL。
而 PostgreSQL 跳出了普通关系型数据库的类型约束,它灵活的支持 JSON, JSONB, XML, 数组等类型。比如说字段类型可以是各种形式的数组,一维或多维。
create table t1( address varchar(5)[3], counter integer[3][3], schedule text[][] )
上面只是认识了一下 PostgreSQL 这一亮眼的特性,本篇重点不在如何定义操作数组类型的字段,而是对于普通的非数组字段类型如何用与数组相关的 unnest 关键字进行记录的批量插入,更新以及合并操作。
在正式使用介入 unnest 之前先熟悉一下 PostgreSQL 的 upsert(update insert) 操作。受其他数据库的影响,总以后 PostgreSQL 也应该支持 merge into 语句,而且竟然 PostgreSQL 官方也有文档介绍 MERGE 有模有样的,然而试了一下根本就不支持 merge into 操作。
普通的 insert upsert 操作
不过 PostgreSQL 有另一种 upsert 的语法,或称之为 insert on conflict,也就是 PostgreSQL 加强版的 insert 语句。如下
INSERT INTO users (id, level) VALUES (1, 0) ON CONFLICT (id) DO UPDATE SET level = users.level + 1;
即插入记录时存在相同的主键可对原记录的某些列进行更新,否则插入该记录。更详细的 insert 语法请参考官方文档 PostgreSQL INSERT。
注意到上面的 upsert 只是应用于处理单条记录,而本文将要讨论到的是批量的处理。我们知道 insert 时可以同时插入多行记录,那么这个 upsert 语法是否也能同时操作多行记录呢?我们大胆假设,小心求证,那就动手一试吧
create table users( id int primary key, level int )
创建一个表 users, 然后插入一条记录
INSERT INTO users (id, level) VALUES (1, 0)
查询 select * from users
表的内容如下
执行批量的 insert
INSERT INTO users (id, level) VALUES (1, 3), (2, 1) ON CONFLICT (id) DO UPDATE SET level = excluded.level;
理看看 users 表中的内容
我们看到已存在行(id=1) 的 level 更新为新的值 3, 并且插入新行。
这里注意到我们用到一个关键字 excluded 用于引用 INSERT 语句中 VALUES 提供的值,相应的表名 users 用于引用表中原有的值。
基于 unnest 的 upsert 操作
前面仍然是写作此文的意外收获,实际上想要总结的是 unnest 关键字在批量操作中的作用。下面来进行演示
create table testunnest( id int primary key, col1 int, col2 varchar(50) )
创建一个表并用 unnest 提供并行数组来进行批量插入
insert into testunnest(id, col1, col2) values (unnest(array[1,2]), unnest(array[30,40]), unnest(array['val1', 'val2']));
这时候表中的内容为
从执行效果来看,它与下面的 insert 语句是等效的
insert into testunnest(id, col1, col2) values (1, 30, 'val1') (2, 40, '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 ("htmlcode">
PreparedStatement pstmt = conn.prepareStatement( "INSERT INTO testunnest(id, col1, col2) " + " VALUES (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("external nofollow" target="_blank" href="https://hashrocket.com/blog/posts/upsert-records-with-postgresql-9-5">Upsert Records with PostgresSQL 9.5
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 雨林唱片《赏》新曲+精选集SACD版[ISO][2.3G]
- 罗大佑与OK男女合唱团.1995-再会吧!素兰【音乐工厂】【WAV+CUE】
- 草蜢.1993-宝贝对不起(国)【宝丽金】【WAV+CUE】
- 杨培安.2009-抒·情(EP)【擎天娱乐】【WAV+CUE】
- 周慧敏《EndlessDream》[WAV+CUE]
- 彭芳《纯色角3》2007[WAV+CUE]
- 江志丰2008-今生为你[豪记][WAV+CUE]
- 罗大佑1994《恋曲2000》音乐工厂[WAV+CUE][1G]
- 群星《一首歌一个故事》赵英俊某些作品重唱企划[FLAC分轨][1G]
- 群星《网易云英文歌曲播放量TOP100》[MP3][1G]
- 方大同.2024-梦想家TheDreamer【赋音乐】【FLAC分轨】
- 李慧珍.2007-爱死了【华谊兄弟】【WAV+CUE】
- 王大文.2019-国际太空站【环球】【FLAC分轨】
- 群星《2022超好听的十倍音质网络歌曲(163)》U盘音乐[WAV分轨][1.1G]
- 童丽《啼笑姻缘》头版限量编号24K金碟[低速原抓WAV+CUE][1.1G]