INSERT — 在表中插入新行
[ WITH [ RECURSIVE ]with_query[, ...] ] INSERT INTOtable_name[ ASalias] [ (column_name[, ...] ) ] [ OVERRIDING { SYSTEM | USER } VALUE ] { DEFAULT VALUES | VALUES ( {expression| DEFAULT } [, ...] ) [, ...] |query} [ ON CONFLICT [conflict_target]conflict_action] [ RETURNING [ WITH ( { OLD | NEW } ASoutput_alias[, ...] ) ] { * |output_expression[ [ AS ]output_name] } [, ...] ] 其中conflict_target可以是以下之一: ( {index_column_name| (index_expression) } [ COLLATEcollation] [opclass] [, ...] ) [ WHEREindex_predicate] ON CONSTRAINTconstraint_name其中conflict_action是以下之一: DO NOTHING DO UPDATE SET {column_name= {expression| DEFAULT } | (column_name[, ...] ) = [ ROW ] ( {expression| DEFAULT } [, ...] ) | (column_name[, ...] ) = (sub-SELECT) } [, ...] [ WHEREcondition]
INSERT将新行插入表中。可以插入由值表达式指定的 一行或多行,也可以插入由查询产生的零行或多行。
目标列名可以按任意顺序列出。如果根本未给出列名列表,则默认使用按 声明顺序排列的全部列;或者如果VALUES子句或 query只提供了N列, 则默认使用按声明顺序排列的前N个列名。 VALUES子句或query 提供的值,会按从左到右的顺序与显式或隐式列列表对应起来。
任何未出现在显式或隐式列列表中的列都会填入默认值;如果没有声明默认 值,则填入空值。
如果任何列的表达式数据类型不正确,将尝试自动进行类型转换。
对没有唯一索引的表执行INSERT不会被并发活动阻塞。 若并发会话执行的操作会锁定或修改与待插入唯一索引值匹配的行,则带有 唯一索引的表可能发生阻塞;详见Section 60.5。 ON CONFLICT可用于指定一种替代动作,而不是报出 违反唯一约束或排他约束的错误。(见下文ON CONFLICT Clause。)
可选的RETURNING子句使INSERT 基于每个实际插入的行(若使用了ON CONFLICT DO UPDATE 子句,则也可能是更新后的行)计算并返回一个或多个值。这主要用于获取 由默认值提供的值,例如 serial 序列号。不过,也允许使用任何引用该表列 的表达式。RETURNING列表的语法与 SELECT的输出列表相同。只有成功插入或更新的行才 会被返回。例如,如果某一行被锁定,但由于不满足 ON CONFLICT DO UPDATE ... WHERE子句中的 condition而未被更新, 则该行不会被返回。
要向表中插入行,必须具有该表上的INSERT权限。 如果存在ON CONFLICT DO UPDATE子句,还要求具有该 表上的UPDATE权限。
如果指定了列列表,你只需要对所列列具有INSERT特 权。类似地,在指定ON CONFLICT DO UPDATE时,你只 需要对列出要更新的列具有UPDATE权限。不过,所有 形式的ON CONFLICT还要求对任何值会被读取的列 具有SELECT权限。这包括 conflict_target中提到的任何列(包括仲裁 约束引用的列),以及ON CONFLICT DO UPDATE的 expression或WHERE子句 condition中提到的任何列。
使用RETURNING子句要求对 RETURNING中提到的所有列具有 SELECT权限。如果使用query子句将查询结果中的行插入表中, 那么当然还需要对查询中用到的任何表或列具有SELECT 权限。
本节介绍仅在插入新行时可用的参数。专门用于 ON CONFLICT子句的参数将单独说明。
with_query #WITH子句允许指定一个或多个子查询,这些子查 询可以在INSERT查询中按名称引用。详见 Section 7.8和SELECT。
query (SELECT语句)本身也可以包含 WITH子句。在这种情况下, query中可以引用两组 with_query,但由于第二组嵌套得更近, 它具有更高的优先级。
table_name #现有表的名称(可选地使用模式限定)。
alias #table_name的替代名 称。提供别名后,它会完全隐藏表的实际名称。当 ON CONFLICT DO UPDATE的目标是一个名为 excluded的表时,这一点特别有用,因为否则 该名称会被当作表示拟插入行的那个特殊表名。
column_name #名为table_name的表 中某一列的名称。如有需要,列名可以附带子字段名或数组下标。 (只向组合列的部分字段插入值时,其余字段将为空值。)在 ON CONFLICT DO UPDATE中引用列时,不要在目 标列的指定中包含表名。例如,INSERT INTO table_name ... ON CONFLICT DO UPDATE SET table_name.col = 1是无效的 (这与UPDATE的一般行为一致)。
OVERRIDING SYSTEM VALUE #如果指定了此子句,那么为标识列提供的任何值都将覆盖默认的序列 生成值。
对于定义为GENERATED ALWAYS的标识列,如果 插入显式值(DEFAULT除外)而未指定 OVERRIDING SYSTEM VALUE或 OVERRIDING USER VALUE,则会报错。(对于定 义为GENERATED BY DEFAULT的标识列, OVERRIDING SYSTEM VALUE本来就是默认行为, 因而显式指定它不会产生任何效果,但 PostgreSQL仍将其作为扩展允许使用。)
OVERRIDING USER VALUE #如果指定了此子句,则会忽略为标识列提供的任何值,并应用默认的 序列生成值。
例如,在表之间复制值时,这个子句很有用。写成 INSERT INTO tbl2 OVERRIDING USER VALUE SELECT * FROM tbl1将从tbl1复制所有在 tbl2中不是标识列的列,而 tbl2中标识列的值将由与 tbl2关联的序列生成。
DEFAULT VALUES #所有列都会填入各自的默认值,就像为每一列都显式指定了 DEFAULT一样。(这种形式不允许出现 OVERRIDING子句。)
expression #赋给相应列的表达式或值。
DEFAULT #相应列将填入其默认值。标识列将填入由关联序列生成的新值。对于 生成列,允许指定该关键字,但这只是表明采用根据其生成表达式计 算该列这一正常行为。
query #提供要插入行的查询(SELECT语句)。其语法 说明请参见SELECT。
output_alias #在RETURNING列表中为OLD 或NEW行指定的可选替代名称。
默认情况下,可通过 OLD. 或column_nameOLD.*返回目标表旧值,通过 NEW. 或column_nameNEW.*返回新值。提供别名后,这些名称会 被隐藏,必须使用别名来引用旧行或新行。例如 RETURNING WITH (OLD AS o, NEW AS n) o.*, n.*。
output_expression #在每一行插入或更新后由INSERT命令计算并返 回的表达式。该表达式可以使用由table_name指定的表中的任何列。 写成*可返回插入或更新后行的全部列。
列名或*可以用OLD或 NEW进行限定,也可以用 OLD或NEW对应的 output_alias进行 限定,以返回旧值或新值。未限定的列名或*, 以及使用目标表名或别名限定的列名或*,都会 返回新值。
对于普通INSERT,所有旧值都为 NULL。但对于带 ON CONFLICT DO UPDATE子句的 INSERT,旧值可能为非NULL。
output_name #用于返回列的名称。
ON CONFLICT 子句可选的ON CONFLICT子句指定一种替代动作,用来 替代抛出唯一约束或排他约束违背错误。对于每一条拟插入的行,要么插入 继续进行;要么如果违反了由conflict_target 指定的某个作为仲裁的约束或索引,就执行替代的 conflict_action。ON CONFLICT DO NOTHING的替代动作只是跳过该行的插入。 ON CONFLICT DO UPDATE的替代动作则是更新与拟插 入行冲突的现有行。
conflict_target可以进行唯一索 引推断。执行推断时,它由一个或多个 index_column_name列 和/或index_expression 表达式,以及可选的index_predicate 组成。所有在不考虑顺序的情况下恰好包含 conflict_target指定列/表达式的 table_name唯一索引, 都会被推断(选中)为仲裁索引。如果指定了 index_predicate,则作 为推断的进一步要求,候选仲裁索引还必须满足该谓词。注意,这意味着如 果存在某个满足其他所有条件的非部分唯一索引(即没有谓词的唯一索 引), 那么该索引也会被推断出来(从而被ON CONFLICT 使用)。如果推断尝试失败,则会报错。
ON CONFLICT DO UPDATE保证得到原子的 INSERT或UPDATE结果;只要 没有其他独立错误,即使在高并发下,也能保证结果是这两者之一。这也称 为UPSERT — “UPDATE or INSERT”。
conflict_target #通过选择仲裁索引来指定 ON CONFLICT对哪些冲突采取替代动作。它要么 执行唯一索引推断,要么显式命名一个约 束。对于ON CONFLICT DO NOTHING,是否指定 conflict_target是可选的;省略时,将处 理与所有可用约束(以及唯一索引)的冲突。对于 ON CONFLICT DO UPDATE,则必须 提供conflict_target。
conflict_action #conflict_action指定一个替代的 ON CONFLICT动作。它可以是 DO NOTHING,也可以是 DO UPDATE子句,用以精确指定发生冲突时要执 行的UPDATE动作细节。在 ON CONFLICT DO UPDATE中, SET和WHERE子句既可以通 过表名(或别名)访问现有行,也可以通过特殊表 excluded访问拟插入的行。如果会读取目标表中 与excluded对应的列,则要求对这些列具有 SELECT权限。
注意,所有行级BEFORE INSERT触发器的效果都 会反映在excluded值中,因为这些效果可能促 成该行被排除在插入之外。
index_column_name #table_name中某一列 的名称。用于推断仲裁索引。遵循CREATE INDEX 的格式。要求对index_column_name 具有SELECT权限。
index_expression #与index_column_name 类似,但用于推断出现在索引定义中的、基于table_name列的表达式(而非简 单列)。遵循CREATE INDEX的格式。要求对 出现在index_expression 中的任何列具有SELECT权限。
collation #指定时,要求相应的index_column_name或 index_expression 必须使用特定的排序规则,才能在推断时匹配。通常会省略,因为 排序规则通常不会影响是否发生约束违背。遵循 CREATE INDEX格式。
opclass #指定时,要求相应的index_column_name或 index_expression 必须使用特定的操作符类,才能在推断时匹配。通常会省略,因为一 种类型的各个操作符类在相等性语义上往往 是等价的,或者只需相信已定义的唯一索引具有所需的相等性定义即 可。遵循CREATE INDEX格式。
index_predicate #用于允许推断部分唯一索引。任何满足该谓词的索引(实际上不一定 是部分索引)都可以被推断。遵循CREATE INDEX 格式。要求对出现在index_predicate 中的任何列具有SELECT权限。
constraint_name #显式按名称指定一个作为仲裁的约束,而不 是通过推断约束或索引。
condition #返回boolean值的表达式。只有使该表达式返回 true的行才会被更新,不过一旦采取 ON CONFLICT DO UPDATE动作,所有行都会被 锁定。请注意,只有在某个冲突已被识别为更新候选后,才会最后计 算condition。
请注意,排他约束不支持在ON CONFLICT DO UPDATE 中充当仲裁对象。在所有情况下,只有NOT DEFERRABLE 约束和唯一索引可作为仲裁对象。
带有ON CONFLICT DO UPDATE子句的 INSERT是一种“确定性”语句。这意 味着不允许该命令对任何单个现有行产生多于一次的影响;一旦出现这种 情况,就会报出基数违背错误。拟插入的行在受仲裁索引或约束限制的属 性上不应彼此重复。
请注意,目前尚不支持在针对分区表的INSERT的 ON CONFLICT DO UPDATE子句中更新冲突行的分区 键,从而需要将该行移动到一个新分区。
通常更推荐使用唯一索引推断,而不是通过 ON CONFLICT ON CONSTRAINT constraint_name直接命 名约束。当底层索引以重叠方式被另一个大致等价的索引替换时,推断仍 能继续正确工作,例如在删除待替换索引之前先使用 CREATE UNIQUE INDEX ... CONCURRENTLY。
当某个唯一索引上正在执行 CREATE INDEX CONCURRENTLY或 REINDEX CONCURRENTLY时,同一张表上的 INSERT ... ON CONFLICT语句可能会意外地因 唯一性违反而失败。
成功完成时,INSERT命令会返回如下形式的命令标签:
INSERToidcount
count是插入或更新的行 数。oid始终为 0(过去,如果 count恰好为 1 且目标表声明为 WITH OIDS,则它是分配给插入行的 OID,否则为 0;但现在已经不再支持创建 WITH OIDS表)。
如果INSERT命令包含RETURNING 子句,则结果将类似于一个SELECT语句,其中包含 RETURNING列表定义的列和值,它们是基于该命令插 入或更新的行计算出来的。
如果指定的表是分区表,则每一行都会被路由到适当的分区并插入其中。 如果指定的表本身就是一个分区,则只要输入行中有任意一行违反该分区 约束,就会报错。
向表films插入一行:
INSERT INTO films VALUES
('UA502', 'Bananas', 105, '1971-07-13', 'Comedy', '82 minutes');
在这个示例中,省略了len列,因此它将取默认值:
INSERT INTO films (code, title, did, date_prod, kind)
VALUES ('T_601', 'Yojimbo', 106, '1961-06-16', 'Drama');
这个示例对日期列使用DEFAULT子句,而不是显式 指定值:
INSERT INTO films VALUES
('UA502', 'Bananas', 105, DEFAULT, 'Comedy', '82 minutes');
INSERT INTO films (code, title, did, date_prod, kind)
VALUES ('T_601', 'Yojimbo', 106, DEFAULT, 'Drama');
要插入一行,其所有列都由默认值构成:
INSERT INTO films DEFAULT VALUES;
使用多行VALUES语法插入多行:
INSERT INTO films (code, title, did, date_prod, kind) VALUES
('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'),
('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy');
这个示例从与films列布局相同的 tmp_films表中选出一些行并插入到 films表:
INSERT INTO films SELECT * FROM tmp_films WHERE date_prod < '2004-05-07';
这个示例向数组列插入值:
-- Create an empty 3x3 gameboard for noughts-and-crosses
INSERT INTO tictactoe (game, board[1:3][1:3])
VALUES (1, '{{" "," "," "},{" "," "," "},{" "," "," "}}');
-- The subscripts in the above example aren't really needed
INSERT INTO tictactoe (game, board)
VALUES (2, '{{X," "," "},{" ",O," "},{" ",X," "}}');
向表distributors插入一行,并返回由 DEFAULT子句生成的序号:
INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets') RETURNING did;
为负责 Acme Corporation 账户的销售人员增加销量计数,并把整个更 新后的行连同当前时间记录到日志表中:
WITH upd AS (
UPDATE employees SET sales_count = sales_count + 1 WHERE id =
(SELECT sales_person FROM accounts WHERE name = 'Acme Corporation')
RETURNING *
)
INSERT INTO employees_log SELECT *, current_timestamp FROM upd;
视情况插入或更新新的分销商。假设已经定义了一个唯一索引,用于约束 出现在did列中的值。请注意,特殊的 excluded表用于引用最初拟插入的值:
INSERT INTO distributors (did, dname)
VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc')
ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname;
按照上例插入或更新新的分销商,并返回任何被更新的既有值以及插入的 新数据。请注意,对于没有冲突的行,返回的old_did 和old_dname值将为NULL:
INSERT INTO distributors (did, dname)
VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc')
ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname
RETURNING old.did AS old_did, old.dname AS old_dname,
new.did AS new_did, new.dname AS new_dname;
插入一个分销商;如果已存在一条会导致待插入行被排除的现有行 (即在行级BEFORE INSERT触发器触发后,其受约 束列与待插入行匹配的行),则对该待插入行不做任何操作。示例假设已 经定义了一个唯一索引,用于约束出现在did列中的 值:
INSERT INTO distributors (did, dname) VALUES (7, 'Redline GmbH')
ON CONFLICT (did) DO NOTHING;
视情况插入或更新新的分销商。示例假设已经定义了一个唯一索引,用于 约束出现在did列中的值。这里使用 WHERE子句来限制实际会被更新的行(不过,任何未 更新的现有行仍会被锁定):
-- Don't update existing distributors based in a certain ZIP code
INSERT INTO distributors AS d (did, dname) VALUES (8, 'Anvil Distribution')
ON CONFLICT (did) DO UPDATE
SET dname = EXCLUDED.dname || ' (formerly ' || d.dname || ')'
WHERE d.zipcode <> '21201';
-- Name a constraint directly in the statement (uses associated
-- index to arbitrate taking the DO NOTHING action)
INSERT INTO distributors (did, dname) VALUES (9, 'Antwerp Design')
ON CONFLICT ON CONSTRAINT distributors_pkey DO NOTHING;
如果可能就插入新的分销商;否则执行 DO NOTHING。示例假设已经定义了一个唯一索引, 用于约束这样一个行子集上的did列值:其中 is_active布尔列计算结果为true:
-- This statement could infer a partial unique index on "did"
-- with a predicate of "WHERE is_active", but it could also
-- just use a regular unique constraint on "did"
INSERT INTO distributors (did, dname) VALUES (10, 'Conrad International')
ON CONFLICT (did) WHERE is_active DO NOTHING;
INSERT符合 SQL 标准,但 RETURNING子句是 PostgreSQL扩展,在 INSERT中使用WITH的能力以及 使用ON CONFLICT指定替代动作的能力也都是扩展。 此外,标准不允许省略列名列表却又不是所有列都由VALUES 子句或query填充的情况。
SQL 标准规定,只有当存在一个定义为总是生成值的标识列时,才能指定 OVERRIDING SYSTEM VALUE。而 PostgreSQL在任何情况下都允许该子句, 并在它不适用时忽略它。
query子句可能存在的限 制见SELECT。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。