插入或更新,是一个很有用的特性,当在主键冲突时可以选择更新数据。在PG中,是使用 ON CONFLICT 来实现这个特性的。
1 2 3 4
INSERTINTO t_role (id, name, created_at) VALUES (3, '普通用户', now()) ON CONFLICT (id) DO UPDATESET name = EXCLUDED.name;
在常用的 INSERT 语句后面用 ON CONFLICT (...) DO .... 语句来指定在某个/些字段出现冲突时需要执行的语句。在 on CONFLICT (...) 里的参数需要是主键或唯一索引(可以为复合字段)。当冲突发生时则会执行 DO .... 后面的语句,这里我们选择更新 name 字段的值。EXCLUDED 是用户引用在 VALUES .... 部分我们将插入的数据,EXCLUDED.name 在这里就是 '普通用户' 。除 DO UPDATE,我们还可以使用 DO NOTHING 来简单的忽略插入时的主键冲突。
SERIAL/BIGSERIAL
看看表 t_user 的结构:
1 2 3 4 5 6 7 8 9 10 11
yangbajing=> \d t_user Table "public.t_user" Column | Type | Collation | Nullable | Default ------------+--------------------------+-----------+----------+------------------------------------ id | bigint | | not null | nextval('t_user_id_seq'::regclass) name | character varying(255) | | not null | roles | integer[] | | not null | data | jsonb | | | created_at | timestamp with time zone | | | Indexes: "t_user_pkey" PRIMARY KEY, btree (id)
/opt/haishu/local/pgsql/10.1/bin/pg_ctl -D /opt/haishu/var/pgsql/10.1_2 -l logfile start waiting for server to start.... done server started
现在,第2个PG数据库已建好,我们分别登录两个数据库。
使用账号:yangbajing 登录第1个PG
1 2 3 4 5 6
$ psql -h localhost -U yangbajing -d yangbajing Password for user yangbajing: psql.bin (10.1) Type "help" for help.
yangbajing=>
使用账号:postgres 登录第2个PG,并创建测试用户 pg2 和测试数据库 pg2
1 2 3 4 5 6 7 8 9 10 11 12
]$ psql -h localhost -p 5433 -U postgres -d postgres Password for user postgres: psql.bin (10.1) Type "help" for help.
postgres=# create user pg2 encrypted password 'pg2'; CREATE ROLE postgres=# create database pg2 owner=pg2 template=template1; CREATE DATABASE postgres=# \c pg2 You are now connected to database "pg2" as user "postgres". pg2=#
pg2=# CREATE SERVER foreign_server FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host 'localhost', port '5432', dbname 'yangbajing'); CREATE SERVER
创建用户映射
1 2
pg2=# CREATE USER MAPPING FOR pg2 SERVER foreign_server OPTIONS (user 'yangbajing', password 'yangbajing'); CREATE USER MAPPING
创建外部表
1 2 3 4 5 6
CREATE FOREIGN TABLE foreign_t_role ( id INT NOT NULL, name VARCHAR(255) NOT NULL, created_at TIMESTAMPTZ ) SERVER foreign_server OPTIONS (schema_name 'public', table_name 't_role');
make USE_PGXS=1 install sudo sudo ldconfig // 重建系统动态链接库缓存
在 MySQL 中创建测试数据
(注:MySQL的使用非本文重点,请自行查阅相关文档)
登录 MySQL 并创建测试表及插入测试数据:
1 2 3 4 5 6 7 8
SET time_zone = '+08:00'; CREATE TABLE t_book( isbn VARCHAR(255) PRIMARY KEY, title VARCHAR(255), created_at DATETIME); INSERT INTO t_book(isbn, title, created_at) VALUES ('978-7-121-32529-8', 'Akka应用模式:分布式应用程序设计实践指南', '2017-10-01'), ('978-7-115-46938-0', 'Kafka技术内幕:图文详解Kafka源码设计与实现', '2017-11-01');
在 PG 中访问 MySQL
类似使用 postgres_fdw,使用 mysql_fdw 也需要 PG 数据库的管理员权限。
1、创建扩展:
1
CREATE EXTENSION mysql_fdw;
2、创建外部服务对象:
1
CREATE SERVER mysql_server FOREIGN DATA WRAPPER mysql_fdw OPTIONS (host '127.0.0.1', port '3306');
3、创建用户映射
1
CREATE USER MAPPING FOR yangbajing SERVER mysql_server OPTIONS(username 'yangbajing', password 'yang.Bajing2018');
4、创建外部表
1 2 3 4 5 6
CREATE FOREIGN TABLE foreign_t_book( isbn VARCHAR(255), title VARCHAR(255), created_at TIMESTAMPTZ ) SERVER mysql_server OPTIONS(dbname 'yangbajing', table_name 't_book'); GRANT ALL ON TABLE foreign_t_book to yangbajing ;
现在,可以在 PG 中访问并使用在 MySQL 中创建的表和数据了,和 postgres_fdw 一样,也可以远程修改原表的内容。