RETURNING

pg 中支持 returning 子句,可以实现相应的功能。目前 PostgreSQL 支持 insert、delete、update 的 returning。

insert returning 返回的是新插入的值。

delete returning 返回的是被删除的值。

update returning 返回的是更新后的值,不能返回更新前的值。

-- 创建示例表
CREATE TABLE test(id serial, name varchar(20));
-- 插入
insert into test(name) values('aa') returning name;
-- 修改
update test set name='bb' where id=1 returning name;
-- 删除
DELETE FROM test_re WHERE id = 1 RETURNING name;

UPSERT

支持 INSERT 语句定义 ON CONFLICT DO UPDATE/IGNORE 属性,当插入 SQL 违反约束的情况下定义动作,而不抛出错误

-- 创建测试数据表
create table t (id int constraint idx_t_id primary key,name varchar(20) constraint cst_name not null);
insert into t values(1,'rudy');
-- 根据字段,当 id 冲突时更新 name 值
insert into t values(1,'rudy1') 
    ON CONFLICT(id) 
    do update set name=EXCLUDED.name;
postgres=# select * from t;
 id | name  
----+-------
  1 | rudy1
  2 | rudy3
-- 也可以直接指定约束名,此时不需要字段,在实际应用中,最好使用字段名
insert into t values(2,'rudy3') 
    ON CONFLICT ON CONSTRAINT idx_t_id 
    do update set name=EXCLUDED.name ; 
postgres=# select * from t;
 id | name  
----+-------
  1 | rudy1
  2 | rudy3
(2 rows)
-- 根据where条件选择性更新,由于id没有大于10的数据,故更新0条数据     
insert into t values(2,'rudy4') 
    ON CONFLICT ON CONSTRAINT idx_t_id
    do update set name=EXCLUDED.name where t.id>10 ;
postgres=# select * from t;
 id | name  
----+-------
  1 | rudy1
  2 | rudy3
-- 只插入满足条件的数据行 
insert into t values(2,'rudy4'),(3,'rudy3') 
    ON CONFLICT(id)
    do nothing ; 
postgres=# select * from t;
 id | name  
----+-------
  1 | rudy1
  2 | rudy3
  3 | rudy3

TABLESAMPLE
SELECT *
  FROM tablename
[ TABLESAMPLE sampling_method ( argument [, …] ) [ REPEATABLE ( seed ) ] ]

TABLESAMPLE 子句表示应该用指定的 sampling_method 来检索表中行的子集。主要包括两种采样 方法:BERNOULLI 和 SYSTEM。

原始抽样方式

select * from test01 order by random() limit 2;

SYSTEM 抽样方式

SYSTEM 抽样方式为随机抽取表上数据块上的数据,理论上每个块被检索的概率是相同的,被选中块中的所有行都会被返回。

-- 抽样银子为 0.01,返回 1% 的数据
-- ctid 第一位表示逻辑数据块编号,第二位表示逻辑块上的数据的逻辑编号
SELECT ctid,* FROM test01 TABLESAMPLE SYSTEM(0.01);
-- 验证
-- 查看块数量
SELECT relname, relpages
  FROM pg_class
 WHERE relname='test01';
-- 数据量/relpages = 每个块记录数
-- 返回量:每个记录数*块数

BERNOULLI

BERNOULLI 为随机抽取表的数据行数据,抽样级别为数据行级别。比 SYSTEM 数量更准确,但性能上低很多

-- 抽样银子为 0.01,返回 1% 的数据
-- ctid 第一位表示逻辑数据块编号,第二位表示逻辑块上的数据的逻辑编号
SELECT ctid,* FROM test01 TABLESAMPLE BERNOULLI(0.01);
-- 验证
-- ctid 显示数据位于不同块上

广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员