且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

PostgreSQL使用函数实现merge功能

更新时间:2022-08-15 17:34:50

PostgreSQL使用函数实现merge功能http://www.bieryun.com/3263.html

PostgreSQL使用函数实现merge功能

实验环境

操作系统:windows 10 家庭中文版

数据库系统: PostgreSQL 9.6.2

说明

oracle数据库中有merge函数,可在插入数据前判断:如果指定列数据不存在,则正常插入数据;如果指定列数据存在,则将此条数据更新为插入的数据。
postgresql数据库中没有类似自带函数,只能自己实现此功能

实验

开启数据库:

psql (9.6.2)
postgres=# \l
                                                         数据库列表
    名称     |  拥有者  | 字元编码 |            校对规则            |             Ctype              |       存取权限   
-------------+----------+----------+--------------------------------+--------------------------------+-----------------------
 ag01xinku   | postgres | UTF8     | Chinese (Simplified)_China.936 | Chinese (Simplified)_China.936 |
 postgres    | postgres | UTF8     | Chinese (Simplified)_China.936 | Chinese (Simplified)_China.936 |
 template0   | postgres | UTF8     | Chinese (Simplified)_China.936 | Chinese (Simplified)_China.936 | =c/postgres          +
             |          |          |                                |                                | postgres=CTc/postgres
 template1   | postgres | UTF8     | Chinese (Simplified)_China.936 | Chinese (Simplified)_China.936 | =c/postgres          +
             |          |          |                                |                                | postgres=CTc/postgres
 test        | postgres | UTF8     | Chinese (Simplified)_China.936 | Chinese (Simplified)_China.936 |
 wcm20171005 | postgres | UTF8     | Chinese (Simplified)_China.936 | Chinese (Simplified)_China.936 |
(6 行记录)


postgres=# \c test

创建测试表db,并插入测试数据:

test=# CREATE TABLE db (a INT PRIMARY KEY, b TEXT);
CREATE TABLE
test=# INSERT INTO db VALUES(1,'1');
INSERT 0 1
test=# INSERT INTO db VALUES(2,'2');
INSERT 0 1
test=# SELECT a,b FROM db;
 a | b
---+---
 1 | 1
 2 | 2
(2 行记录)

针对这个表创建merge函数:

test=# CREATE FUNCTION merge_db(key INT, data TEXT) RETURNS VOID AS
test-# $$
test$# BEGIN
test$#    LOOP
test$#        UPDATE db SET b = data WHERE a = key;
test$#        IF found THEN
test$#            RETURN;
test$#        END IF;
test$#
test$#        BEGIN
test$#            INSERT INTO db(a,b) VALUES (key, data);
test$#            RETURN;
test$#        EXCEPTION WHEN unique_violation THEN
test$#            -- do nothing
test$#        END;
test$#    END LOOP;
test$# END;
test$# $$
test-# LANGUAGE plpgsql;
CREATE FUNCTION

测试

使用merge函数插入key列字段已经在表中存在的数据:

test=# SELECT merge_db(1, 'a');
 merge_db
----------

(1 行记录)

检查可发现,key字段为1的数据被更新了

test=# SELECT a,b FROM db;
 a | b
---+---
 2 | 2
 1 | a
(2 行记录)

再尝试使用merge函数插入key列字段已经在表中不存在的数据:

test=# SELECT merge_db(3, 'c');
 merge_db
----------

(1 行记录)

检查可发现数据直接插入了表中

test=# SELECT a,b FROM db;
 a | b
---+---
 2 | 2
 1 | a
 3 | c
(3 行记录)

功能实现!

小结

此方法只实现了oracle中merge函数的部分功能,而最大的问题是必须针对每个表创建自己的merge函数,比较适合在进行数据库迁移的时候配合外部表和触发器使用,而在正常业务环境中使用机会不多。