INSERT
功能描述
注意事项
语法格式
[ WITH [ RECURSIVE ] with_query [, ...] ]
INSERT INTO table_name [ ( column_name [, ...] ) ]
{ DEFAULT VALUES
| VALUES {( { expression | DEFAULT } [, ...] ) }[, ...]
| query }
[ ON DUPLICATE KEY UPDATE {{ column_name = { expression | DEFAULT } } [, ...] | NOTHING} ]
[ RETURNING {* | {output_expression [ [ AS ] output_name ] }[, ...]} ];
参数说明
-
WITH [ RECURSIVE ] with_query [, …]
用于声明一个或多个可以在主查询中通过名称引用的子查询,相当于临时表。
如果声明了RECURSIVE,那么允许SELECT子查询通过名称引用它自己。
其中with_query的详细格式为:with_query_name [ ( column_name [, …] ) ] AS
( {select | values | insert | update | delete} )
– with_query_name指定子查询生成的结果集名称,在查询中可使用该名称访问
– 每个子查询可以是SELECT,VALUES,INSERT,UPDATE或DELETE语句。
-
返回实际插入的行,RETURNING列表的语法与SELECT的输出列表一致。注意:INSERT ON DUPLICATE KEY UPDATE不支持RETURNING子句。
-
如果表中存在多个唯一约束,如果所插入数据违反多个唯一约束,对于检测到冲突的第一行进行更新,其他冲突行不更新(检查顺序与索引维护具有强相关性,一般先创建的索引先进行冲突检查)。
-
说明:
当GUC参数 enable_upsert_to_merge 为 on 时,此条INSERT ON DUPLICATE KEY UPDATE语句(UPSERT语句)会被转换成一条具有同等语义的MERGE INTO语句,之后的行为与MERGE INTO相同,在如下行为中与UPSERT将会不同:- 不支持UPDATE更新自定义类型或者数组类型的元素的值
- 如果INSERT指定了目标列,那么仅检查只包含目标列或设有DEFAULT值的列的唯一约束或主键约束冲突。
- 当表中存在多个唯一约束,如果所插入数据与表中多个行都存在唯一约束冲突,所有冲突行都会执行UPDATE子句完成更新。
- 如果插入多行,这些行均与表中同一行数据存在唯一约束冲突,执行会失败。需设置GUC参数 behavior_compat_options ='merge_update_multi',允许该对冲突行会执行多次UPDATE。
- 如果插入多行,这些行与表中已有数据不存在唯一约束冲突,但是相互违反唯一约束时,INSERT执行失败。
- 在多行插入场景,执行性能较差。由于MERGE INTO不支持并发更新,在多行插入情况下,容易出现报错导致事务回滚。
- 通过EXPLAIN 显示的计划为转换为MERGE INTO语句的执行计划。
示例
--创建表tpcds.reason_t2。
postgres=# CREATE TABLE tpcds.reason_t2
r_reason_sk integer,
r_reason_id character(16),
r_reason_desc character(100)
--向表中插入一条记录。
postgres=# INSERT INTO tpcds.reason_t2(r_reason_sk, r_reason_id, r_reason_desc) VALUES (1, 'AAAAAAAABAAAAAAA', 'reason1');
--向表中插入一条记录,和上一条语法等效。
postgres=# INSERT INTO tpcds.reason_t2 VALUES (2, 'AAAAAAAABAAAAAAA', 'reason2');
--向表中插入多条记录。
postgres=# INSERT INTO tpcds.reason_t2 VALUES (3, 'AAAAAAAACAAAAAAA','reason3'),(4, 'AAAAAAAADAAAAAAA', 'reason4'),(5, 'AAAAAAAAEAAAAAAA','reason5');
--向表中插入tpcds.reason中r_reason_sk小于5的记录。
postgres=# INSERT INTO tpcds.reason_t2 SELECT * FROM tpcds.reason WHERE r_reason_sk <5;
--对表创建唯一索引
postgres=# CREATE UNIQUE INDEX reason_t2_u_index ON tpcds.reason_t2(r_reason_sk);
--向表中插入多条记录,如果冲突则更新冲突数据行中r_reason_id字段为'BBBBBBBBCAAAAAAA'。
postgres=# INSERT INTO tpcds.reason_t2 VALUES (5, 'BBBBBBBBCAAAAAAA','reason5'),(6, 'AAAAAAAADAAAAAAA', 'reason6') ON DUPLICATE KEY UPDATE r_reason_id = 'BBBBBBBBCAAAAAAA';
--向表中插入多条记录,如果冲突则忽略此条插入。
postgres=# INSERT INTO tpcds.reason_t2 VALUES (5, 'BBBBBBBBCAAAAAAA','reason5'),(6, 'AAAAAAAADAAAAAAA', 'reason6') ON DUPLICATE KEY UPDATE NOTHING;
--向表中插入多条记录,如果冲突则更新冲突数据行中r_reason_id字段为插入数据的r_reason_id值。
postgres=# INSERT INTO tpcds.reason_t2 VALUES (5, 'BBBBBBBBCAAAAAAA','reason5'),(6, 'AAAAAAAADAAAAAAA', 'reason6') ON DUPLICATE KEY UPDATE r_reason_id = EXCLUDED.r_reason_id;
postgres=# INSERT INTO tpcds.reason_t2 VALUES (5, 'BBBBBBBBCAAAAAAA','reason5'),(6, 'AAAAAAAADAAAAAAA', 'reason6') ON DUPLICATE KEY UPDATE r_reason_id = values(r_reason_id);
--删除表tpcds.reason_t2。
postgres=# DROP TABLE tpcds.reason_t2;