PostgreSQL数据实时转换

pg中我们可以通过create rule的方式来实现将入库的数据实时转换成另一种格式,例如我们要存入json类型数据,可以直接存JSON,也可以存格式化数据,甚至可以在导入时,自动将JSON转成结构化数据。那么我们就可以使用实时数据转换的方式。
但是rule的方式有一点不足,对于通过copy协议插入的数据无法做到实时转换,那我们该怎么办呢?通过pg中的触发器不失为一种好的方法。

例子:
1、rule转换
–创建原表

postgis=#  create table tt1(id int, c1 numeric, c2 numeric);
CREATE TABLE

–创建目标表

postgis=#  create table tt2(id int,geo geometry);
CREATE TABLE

下面创建规则,用来实现将插入tt1的数据c1,c2转换成tt2的geo列的point的横纵坐标。
–创建规则

postgis=# create rule r1 as on insert to tt1 do instead insert into tt2 values (NEW.id,
postgis(# ST_MakePoint(NEW.c1,NEW.c2));
CREATE RULE

–插入数据

postgis=# insert into tt1 values(1,1,1);
INSERT 0 1

–查看
可以发现表tt1中没有数据,数据插入到表tt2中了

postgis=# select * from tt1;
 id | c1 | c2 
----+----+----
(0 rows)
postgis=# select id,st_astext(geo) from tt2;
 id | st_astext  
----+------------
  1 | POINT(1 1)
(1 row)

2、rule转换json数据
–创建原表

bill=# create table t1 (id int, info text, j jsonb);  
CREATE TABLE

–目标表

bill=# create table t2 (id int, info text, c1 int, c2 int, c3 text);  
CREATE TABLE

–在源表创建规则,自动将JSONB非结构化数据,转换为结构化数据插入

bill=#  create rule r1 as on insert to t1 do instead insert into t2 values (NEW.ID, NEW.INFO, ((NEW.J)->>'c1')::int, ((NEW.j)->>'c2')::int, (NEW.j)->>'c3');  
CREATE RULE

–插入数据测试

bill=# insert into t1 values (1,'test',jsonb '{"c1":1, "c2":2, "c3":"text"}');
INSERT 0 1
bill=# select * from t1;
 id | info | j 
----+------+---
(0 rows)

bill=# select * from t2;
 id | info | c1 | c2 |  c3  
----+------+----+----+------
  1 | test |  1 |  2 | text
(1 row)

–copy命令测试,可以发现copy不会触发rule

bill=# copy (select 1,'test',jsonb '{"c1":1, "c2":2, "c3":"text"}') to '/home/pg12/test';      
COPY 1
bill=# copy t1 from '/home/pg12/test';     
COPY 1
bill=# select * from t1;  
 id | info |                j                 
----+------+----------------------------------
  1 | test | {"c1": 1, "c2": 2, "c3": "text"}
(1 row)

bill=# select * from t2;
 id | info | c1 | c2 |  c3  
----+------+----+----+------
  1 | test |  1 |  2 | text
(1 row)

3、trigger转换
–删除rule

bill=# drop rule r1 on t1;  
DROP RULE

–创建触发器函数

bill=# create or replace function tg() returns trigger as $$  
bill$#   declare  
bill$#   begin  
bill$#     insert into t2 values (NEW.ID, NEW.INFO, ((NEW.J)->>'c1')::int, ((NEW.j)->>'c2')::int, (NEW.j)->>'c3');  
bill$#     return null;  
bill$#   end;  
bill$#   $$ language plpgsql strict;  
CREATE FUNCTION

–创建触发器

bill=# create trigger tg before insert on t1 for each row execute procedure tg();
CREATE TRIGGER

–重新测试
可以发现insert和copy都将数据转换插入到目标表中了。

bill=# truncate t1;
TRUNCATE TABLE
bill=# truncate t2;
TRUNCATE TABLE
bill=# copy t1 from '/home/pg12/test';
COPY 0
bill=# insert into t1 values (1,'test',jsonb '{"c1":1, "c2":2, "c3":"text"}');  
INSERT 0 0
bill=# select * from t2;
 id | info | c1 | c2 |  c3  
----+------+----+----+------
  1 | test |  1 |  2 | text
  1 | test |  1 |  2 | text
(2 rows)

bill=# select * from t1;
 id | info | j 
----+------+---
(0 rows)

总结:
对于数据的实时转换:如果不需要支持COPY,用rule就可以了。如果需要支持copy和insert, 则需要使用触发器。

发布了70 篇原创文章 · 获赞 5 · 访问量 3118

猜你喜欢

转载自blog.csdn.net/weixin_39540651/article/details/103952304