受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: 19 / devel
此文档适用于不受支持的 PostgreSQL 版本。
您可能需要查看当前版本的相同页面,或上面列出的其他受支持版本。

INSERT

INSERT — 在表中插入新行

Synopsis

[ WITH [ RECURSIVE ] with_query [, ...] ]
INSERT INTO table_name [ AS alias ] [ ( column_name [, ...] ) ]
    [ OVERRIDING { SYSTEM | USER } VALUE ]
    { DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query }
    [ ON CONFLICT [ conflict_target ] conflict_action ]
    [ RETURNING [ WITH ( { OLD | NEW } AS output_alias [, ...] ) ]
                { * | output_expression [ [ AS ] output_name ] } [, ...] ]

其中 conflict_target 可以是以下之一:

    ( { index_column_name | ( index_expression ) } [ COLLATE collation ] [ opclass ] [, ...] ) [ WHERE index_predicate ]
    ON CONSTRAINT constraint_name

其中 conflict_action 是以下之一:

    DO NOTHING
    DO SELECT [ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } ] [ WHERE condition ]
    DO UPDATE SET { column_name = { expression | DEFAULT } |
                    ( column_name [, ...] ) = [ ROW ] ( { expression | DEFAULT } [, ...] ) |
                    ( column_name [, ...] ) = ( sub-SELECT )
                  } [, ...]
              [ WHERE condition ]

描述

INSERT将新行插入表中。可以插入由值表达式指定的 一行或多行,也可以插入由查询产生的零行或多行。

目标列名可以按任意顺序列出。如果根本未给出列名列表,则默认使用按 声明顺序排列的全部列;或者如果VALUES子句或 query只提供了N列, 则默认使用按声明顺序排列的前N个列名。 VALUES子句或query 提供的值,会按从左到右的顺序与显式或隐式列列表对应起来。

任何未出现在显式或隐式列列表中的列都会填入默认值;如果没有声明默认 值,则填入空值。

如果任何列的表达式数据类型不正确,将尝试自动进行类型转换。

对没有唯一索引的表执行INSERT不会被并发活动阻塞。 若并发会话执行的操作会锁定或修改与待插入唯一索引值匹配的行,则带有 唯一索引的表可能发生阻塞;详见Section 63.5ON CONFLICT可用于指定一种替代动作,而不是报出 违反唯一约束或排他约束的错误。(见下文ON CONFLICT Clause。)

可选的RETURNING子句使INSERT 基于每个实际插入的行(若使用了ON CONFLICT DO SELECT/UPDATE 子句,则也可能是被选中或更新后的行)计算并返回一个或多个值。这主要用于获取 由默认值提供的值,例如 serial 序列号。不过,也允许使用任何引用该表列 的表达式。RETURNING列表的语法与 SELECT的输出列表相同。只有成功插入、更新或选中的行才 会被返回。例如,如果某一行被锁定,但由于不满足 ON CONFLICT ... WHERE子句中的 condition而未被更新或选中, 则该行不会被返回。

要向表中插入行,必须具有该表上的INSERT权限。 如果存在ON CONFLICT DO UPDATE子句,还要求具有该 表上的UPDATE权限。如果存在ON CONFLICT DO SELECT, 则还要求具有该表上的SELECT权限。如果使用 ON CONFLICT DO SELECT FOR UPDATE/SHARE, 则除了SELECT权限外,还要求至少对一列具有 UPDATE权限。

如果指定了列列表,你只需要对所列列具有INSERT特 权。类似地,在指定ON CONFLICT DO UPDATE时,你只 需要对列出要更新的列具有UPDATE权限。不过,所有 形式的ON CONFLICT还要求对任何值会被读取的列 具有SELECT权限。这包括 conflict_target中提到的任何列(包括仲裁 约束引用的列),以及ON CONFLICT DO UPDATEexpressionWHERE子句 condition中提到的任何列。

使用RETURNING子句要求对 RETURNING中提到的所有列具有 SELECT权限。如果使用query子句将查询结果中的行插入表中, 那么当然还需要对查询中用到的任何表或列具有SELECT 权限。

参数

插入

本节介绍仅在插入新行时可用的参数。专门用于 ON CONFLICT子句的参数将单独说明。

with_query #

WITH子句允许指定一个或多个子查询,这些子查 询可以在INSERT查询中按名称引用。详见 Section 7.8SELECT

querySELECT语句)本身也可以包含 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 VALUEOVERRIDING 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列表中为OLDNEW行指定的可选替代名称。

默认情况下,可通过 OLD.column_nameOLD.*返回目标表旧值,通过 NEW.column_nameNEW.*返回新值。提供别名后,这些名称会 被隐藏,必须使用别名来引用旧行或新行。例如 RETURNING WITH (OLD AS o, NEW AS n) o.*, n.*

output_expression #

在每一行插入或更新后由INSERT命令计算并返 回的表达式。该表达式可以使用由table_name指定的表中的任何列。 写成*可返回插入或更新后行的全部列。

列名或*可以用OLDNEW进行限定,也可以用 OLDNEW对应的 output_alias进行 限定,以返回旧值或新值。未限定的列名或*, 以及使用目标表名或别名限定的列名或*,都会 返回新值。

对于普通INSERT,所有旧值都为 NULL。但对于带 ON CONFLICT DO SELECT/UPDATE子句的 INSERT,旧值可能为非NULL。 如果走的是SELECT路径,则新值与旧值相同, 因为并不会发生修改。

output_name #

用于返回列的名称。

ON CONFLICT 子句

可选的ON CONFLICT子句指定一种替代动作,用来 替代抛出唯一约束或排他约束违背错误。对于每一条拟插入的行,要么插入 继续进行;要么如果违反了由conflict_target 指定的某个作为仲裁的约束或索引,就执行替代的 conflict_actionON CONFLICT DO NOTHING的替代动作只是跳过该行的插入。 ON CONFLICT DO UPDATE的替代动作则是更新与拟插 入行冲突的现有行。ON CONFLICT DO SELECT则返回 与拟插入行冲突的现有行,并可选择加行级锁。

conflict_target可以进行唯一索 引推断。执行推断时,它由一个或多个 index_column_name列 和/或index_expression 表达式,以及可选的index_predicate 组成。所有在不考虑顺序的情况下恰好包含 conflict_target指定列/表达式的 table_name唯一索引, 都会被推断(选中)为仲裁索引。如果指定了 index_predicate,则作 为推断的进一步要求,候选仲裁索引还必须满足该谓词。注意,这意味着如 果存在某个满足其他所有条件的非部分唯一索引(即没有谓词的唯一索 引), 那么该索引也会被推断出来(从而被ON CONFLICT 使用)。如果推断尝试失败,则会报错。

ON CONFLICT DO UPDATE保证得到原子的 INSERTUPDATE结果;只要 没有其他独立错误,即使在高并发下,也能保证结果是这两者之一。这也称 为UPSERTUPDATE or INSERT

ON CONFLICT DO SELECT同样保证得到原子的 INSERTSELECT结果。这也 称为幂等插入get or create。 对于ON CONFLICT DO SELECT必须 提供RETURNING子句。

conflict_target #

通过选择仲裁索引来指定 ON CONFLICT对哪些冲突采取替代动作。它要么 执行唯一索引推断,要么显式命名一个约 束。对于ON CONFLICT DO NOTHING,是否指定 conflict_target是可选的;省略时,将处 理与所有可用约束(以及唯一索引)的冲突。对于 ON CONFLICT DO UPDATEON CONFLICT DO SELECT,则必须 提供conflict_target

conflict_action #

conflict_action指定一个替代的 ON CONFLICT动作。它可以是 DO NOTHING、允许返回冲突行的 DO SELECT子句,或者在发生冲突时精确指定 UPDATE动作细节的DO UPDATE 子句。

DO UPDATE中的SET子句, 以及DO SELECTDO UPDATE 中的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_nameindex_expression 必须使用特定的排序规则,才能在推断时匹配。通常会省略,因为 排序规则通常不会影响是否发生约束违背。遵循 CREATE INDEX格式。

opclass #

指定时,要求相应的index_column_nameindex_expression 必须使用特定的操作符类,才能在推断时匹配。通常会省略,因为一 种类型的各个操作符类在相等性语义上往往 是等价的,或者只需相信已定义的唯一索引具有所需的相等性定义即 可。遵循CREATE INDEX格式。

index_predicate #

用于允许推断部分唯一索引。任何满足该谓词的索引(实际上不一定 是部分索引)都可以被推断。遵循CREATE INDEX 格式。要求对出现在index_predicate 中的任何列具有SELECT权限。

constraint_name #

显式按名称指定一个作为仲裁的约束,而不 是通过推断约束或索引。

FOR UPDATE
FOR NO KEY UPDATE
FOR SHARE
FOR KEY SHARE #

如果在ON CONFLICT DO SELECT子句中指定这些 形式,则冲突的表行会被锁定,以防并发更新。详见 The Locking ClauseSELECT 文档。

condition #

返回boolean值的表达式。只有使该表达式返回 true的行才会被更新或选中返回,不过一旦指 定ON CONFLICT DO UPDATEON CONFLICT DO SELECT FOR UPDATE/SHARE, 所有冲突行都会被锁定。请注意,只有在某个冲突已被识别为更新或 选中候选后,才会最后计算condition

请注意,排他约束不支持在ON CONFLICT DO SELECT/UPDATE 中充当仲裁对象。在所有情况下,只有NOT DEFERRABLE 约束和唯一索引可作为仲裁对象。

带有ON CONFLICT DO UPDATE子句的 INSERT是一种确定性语句。这意 味着不允许该命令对任何单个现有行产生多于一次的影响;一旦出现这种 情况,就会报出基数违背错误。拟插入的行在受仲裁索引或约束限制的属 性上不应彼此重复。

请注意,目前尚不支持在针对分区表的INSERTON CONFLICT DO UPDATE子句中更新冲突行的分区 键,从而需要将该行移动到一个新分区。

Tip

通常更推荐使用唯一索引推断,而不是通过 ON CONFLICT ON CONSTRAINT constraint_name直接命 名约束。当底层索引以重叠方式被另一个大致等价的索引替换时,推断仍 能继续正确工作,例如在删除待替换索引之前先使用 CREATE UNIQUE INDEX ... CONCURRENTLY

输出

成功完成时,INSERT命令会返回如下形式的命令标签:

INSERT oid count

count是插入、更新或选中 返回的行数。oid始终为 0(过去,如果 count恰好为 1 且目标表声明为 WITH OIDS,则它是分配给插入行的 OID,否则为 0;但现在已经不再支持创建 WITH OIDS表)。

如果INSERT命令包含RETURNING 子句,则结果将类似于一个SELECT语句,其中包含 RETURNING列表定义的列和值,它们是基于该命令插 入、更新或选中的行计算出来的。

注解

如果指定的表是分区表,则每一行都会被路由到适当的分区并插入其中。 如果指定的表本身就是一个分区,则只要输入行中有任意一行违反该分区 约束,就会报错。

也可以考虑使用MERGE,因为它允许在单条语句中混 合INSERTUPDATEDELETE。参见MERGE

示例

向表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_didold_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;

如果可能就插入新的分销商;否则返回现有的分销商行。示例假设已经定 义了一个唯一索引,用于约束出现在did列中的值。 这对 get-or-create 模式很有用:

INSERT INTO distributors (did, dname) VALUES (11, 'Global Electronics')
    ON CONFLICT (did) DO SELECT
    RETURNING *;

如果新分销商的 ID 不匹配,则插入它;否则,如果其名称不匹配,则返 回现有行:

INSERT INTO distributors AS d (did, dname) VALUES (12, 'Micro Devices Inc')
    ON CONFLICT (did) DO SELECT WHERE d.dname != EXCLUDED.dname
    RETURNING *;

插入一个新分销商,或返回并锁定现有行以便更新。当你需要确保对该行 的独占访问时,这很有用:

INSERT INTO distributors (did, dname) VALUES (13, 'Advanced Systems')
    ON CONFLICT (did) DO SELECT FOR UPDATE
    RETURNING *;

如果可能就插入新的分销商;否则执行 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填充的情况。如果你希望使用 比ON CONFLICT更符合 SQL 标准的语句,请参见 MERGE

SQL 标准规定,只有当存在一个定义为总是生成值的标识列时,才能指定 OVERRIDING SYSTEM VALUE。而 PostgreSQL在任何情况下都允许该子句, 并在它不适用时忽略它。

query子句可能存在的限 制见SELECT