2025年9月25日: PostgreSQL 18 发布!
支持的版本: 当前 (18) / 17 / 16 / 15 / 14 / 13
开发版本: devel
不再支持的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1

INSERT

INSERT — 创建表中的新行

概要

[ 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 ] } [, ...] ]

where conflict_target can be one of:

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

and conflict_action is one of:

    DO NOTHING
    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 提供的这些值将从左到右与显式或隐式指定的列列表对应。

显式或隐式列列表中不存在的每一列都将用默认值填充,如果声明了默认值,则使用声明的默认值,否则使用 NULL。

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

INSERT 到没有唯一索引的表不会被并发活动阻止。具有唯一索引的表可能会被阻止,如果并发会话执行的操作锁定或修改与要插入的唯一索引值匹配的行;详细信息请参阅 第 63.5 节。可以使用 ON CONFLICT 指定一个替代操作,以代替引发唯一约束或排除约束冲突错误。(请参阅下面的 ON CONFLICT 子句。)

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

为了插入数据,您必须对目标表具有 INSERT 权限。如果存在 ON CONFLICT DO UPDATE,则还需要对该表具有 UPDATE 权限。

如果指定了列列表,则只需要对列出的列具有 INSERT 权限。类似地,在指定 ON CONFLICT DO UPDATE 时,只需要对要更新的列具有 UPDATE 权限。但是,ON CONFLICT DO UPDATE 还要求对在 ON CONFLICT DO UPDATE 表达式或 condition 中读取的任何列具有 SELECT 权限。

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

参数

插入

本节介绍仅在插入新行时可能使用的参数。 ON CONFLICT 子句一起使用的参数将单独描述。

with_query

WITH 子句允许您指定一个或多个子查询,这些子查询可以在 INSERT 查询中通过名称引用。有关详细信息,请参阅 第 7.8 节SELECT

可以使 querySELECT 语句)也包含 WITH 子句。在这种情况下,两个 with_query 都可以引用 query 内部,但第二个优先级更高,因为它嵌套得更深。

table_name

一个现有表的名称(可选择模式限定)。

alias

table_name 的替代名称。提供别名时,它会完全隐藏表的实际名称。当 ON CONFLICT DO UPDATE 目标表名为 excluded 时,这特别有用,因为否则它会被解释为表示要插入的行的特殊表的名称。

column_name

table_name 指定的表中的列的名称。如果需要,列名可以由子字段名或数组下标限定。(仅插入复合列的某些字段会将其他字段保留为 NULL。)引用列名时,请不要在目标列的规范中包含表名。例如,INSERT INTO table_name ... ON CONFLICT DO UPDATE SET table_name.col = 1 是无效的(这遵循 UPDATE 的一般行为)。

OVERRIDING SYSTEM VALUE

如果指定了此子句,则为标识列提供的任何值将覆盖默认的序列生成值。

对于定义为 GENERATED ALWAYS 的标识列,在不指定 OVERRIDING SYSTEM VALUEOVERRIDING USER VALUE 的情况下,插入显式值(DEFAULT 除外)是错误的。(对于定义为 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 UPDATE 子句的 INSERT,旧值可能不是 NULL

output_name

用于返回列的名称。

ON CONFLICT Clause

可选的 ON CONFLICT 子句指定一个替代操作,以代替引发唯一冲突或排除约束冲突错误。对于要插入的每一行,要么继续插入,要么,如果 conflict_target 指定的 仲裁约束或索引被违反,则执行替代的 conflict_actionON CONFLICT DO NOTHING 仅避免插入一行作为其替代操作。ON CONFLICT DO UPDATE 将要插入的行与已有的冲突行进行更新作为其替代操作。

conflict_target 可以执行 唯一索引推断。在进行推断时,它由一个或多个 index_column_name 列和/或 index_expression 表达式组成,以及一个可选的 index_predicate。所有 table_name 的唯一索引,如果不考虑顺序,完全包含 conflict_target 指定的列/表达式,将被推断(选择)为仲裁索引。如果指定了 index_predicate,则它必须作为推断的进一步要求,满足仲裁索引。请注意,这意味着非部分唯一索引(没有谓词的唯一索引)将被推断(因此由 ON CONFLICT 使用),前提是存在满足所有其他标准的索引。如果推断尝试失败,则会引发错误。

ON CONFLICT DO UPDATE 保证了原子 INSERTUPDATE 的结果;只要没有独立错误,即使在高并发下,也会保证其中一个结果。这也称为 UPSERT —— 更新或插入

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 中的 SETWHERE 子句可以使用表的名称(或别名)访问现有行,并使用特殊表 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

通过名称显式指定仲裁 约束,而不是推断约束或索引。

condition

返回 boolean 类型值的表达式。只有当该表达式返回 true 时,才会更新行,尽管在采取 ON CONFLICT DO UPDATE 操作时,所有行都会被锁定。请注意,condition 是最后计算的,在冲突被确定为要更新的候选之后。

请注意,排除约束不支持作为 ON CONFLICT DO UPDATE 的仲裁器。在所有情况下,仅支持 NOT DEFERRABLE 约束和唯一索引作为仲裁器。

INSERT 带有 ON CONFLICT DO UPDATE 子句是一个 确定性 语句。这意味着该命令不允许影响任何单个现有行超过一次;当这种情况发生时,将引发基数冲突错误。要插入的行在由仲裁索引或约束约束的属性方面不应相互重复。

请注意,目前不支持将应用于分区表的 INSERTON CONFLICT DO UPDATE 子句更新冲突行的分区键,使其需要将行移动到新分区。

提示

通常最好使用唯一索引推断,而不是直接命名约束,例如使用 ON CONFLICT ON CONSTRAINT constraint_name。当底层索引被另一个或多或少等效的索引以重叠方式替换时,推断将继续正常工作,例如在使用 CREATE UNIQUE INDEX ... CONCURRENTLY 之后删除被替换的索引。

输出

成功完成时,INSERT 命令将返回一个命令标签,格式为

INSERT oid count

count 是插入或更新的行数。 oid 始终为 0(它以前是OID如果 count 恰好为一且目标表声明为 WITH OIDS,则分配给插入的行,否则为 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');

此示例将一些行从 tmp_films 表插入到 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 row 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 未填充所有列的情况。如果您偏好比 ON CONFLICT 更符合 SQL 标准的语句,请参阅 MERGE

SQL 标准规定,只有在存在总是生成的标识列时才能指定 OVERRIDING SYSTEM VALUE。PostgreSQL 在任何情况下都允许此子句,如果它不适用则忽略它。

query 子句的可能限制已在 SELECT 下进行了说明。

提交更正

如果您在文档中看到任何不正确、与您的实际使用经验不符或需要进一步澄清的内容,请使用 此表格 来报告文档问题。