PostgreSQL多表插入(兼容oracle insert all)

我们想把一个查询语句返回的结果集插入到多个目标表中。例如,希望把A表的数据分别插入到 B 表、C 表和 D 表。这3个表与 A 表的结构相同(相同的列和数据类型),并且当前不含任何数据。

解决办法就是把查询结果插入到多个目标表中。在oracle中我们可以使用insert all或者insert first语句,两者语法基本一致,区别在于:

  • insert first:对于每一行数据,只插入到第一个when条件成立的表,不继续检查其他条件。

  • insert all :对于每一行数据,对每一个when条件都进行检查,如果满足条件就执行插入操作。

但是在pg中是不支持该语法的,那么我们该如何实现多表插入的功能呢?

例子:
先看看在oracle中insert all的效果:

SQL> create table a(id int, c1 int, c2 int);  

Table created.

SQL> create table b(id int, c1 int, c2 int);  

Table created.
SQL> set autotrace on;  
SQL> insert all   
  2    into a (id,c1) values (id, col1)  
  3    into b (id,c2) values (id, col2)  
  4  select rownum as id, trunc(dbms_random.value(0, 100)) as col1, trunc(dbms_random.value(0, 100)) as col2 from dual connect by level <=10000;  

20000 rows created.


Execution Plan
----------------------------------------------------------
Plan hash value: 702343910

--------------------------------------------------------------------------------
--------

| Id  | Operation                       | Name | Rows  | Bytes | Cost (%CPU)| Ti
me     |

--------------------------------------------------------------------------------
--------

|   0 | INSERT STATEMENT                |      |     1 |    39 |     2   (0)| 00
:00:01 |

|   1 |  MULTI-TABLE INSERT             |      |       |       |            |
       |

|   2 |   VIEW                          |      |     1 |    39 |     2   (0)| 00
:00:01 |

|   3 |    COUNT                        |      |       |       |            |
       |

|*  4 |     CONNECT BY WITHOUT FILTERING|      |       |       |            |
       |

|   5 |      FAST DUAL                  |      |     1 |       |     2   (0)| 00
:00:01 |

|   6 |   INTO                          | A    |       |       |            |
       |

|   7 |   INTO                          | B    |       |       |            |
       |

--------------------------------------------------------------------------------
--------


Predicate Information (identified by operation id):
---------------------------------------------------

   4 - filter(LEVEL<=10000)


Statistics
----------------------------------------------------------
       1152  recursive calls
        345  db block gets
       1782  consistent gets
        201  physical reads
     376608  redo size
        842  bytes sent via SQL*Net to client
       1140  bytes received via SQL*Net from client
          3  SQL*Net roundtrips to/from client
         35  sorts (memory)
          0  sorts (disk)
      20000  rows processed

在pg中我们可以使用CTE语句来实现该功能。
建表:

bill=# create table a(id int, c1 int, c2 int);  
CREATE TABLE
bill=# create table b(id int, c1 int, c2 int);  
CREATE TABLE

可以发现pg不支持insert all语法:

bill=# insert all   
bill-#   into a (id,c1) values (id, col1)  
bill-#   into b (id,c2) values (id, col2)  
bill-# select id, random() col1, random() col2 from generate_series(1,10000) t(id);  
psql: ERROR:  syntax error at or near "all"
LINE 1: insert all   
               ^

使用CTE语句进行多表插入:

bill=# with tmp as (select id, random() col1, random() col2 from generate_series(1,10000) t(id)),  
bill-# ins1 as (insert into a (id,c1) select id,col1 from tmp)  
bill-# insert into b (id,c2) select id,col2 from tmp;  
INSERT 0 10000
bill=# select count(*) from a;
 count 
-------
 10000
(1 row)

bill=# select count(*) from b;
 count 
-------
 10000
(1 row)

参考链接:
Oracle insert all 的语法:
https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_9014.htm
https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_9014.htm#i2125362

pg CTE语法:
https://www.postgresql.org/docs/11/static/queries-with.html

发布了116 篇原创文章 · 获赞 50 · 访问量 1万+

猜你喜欢

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