Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16

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 * | 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 在表中插入新行。可以插入由值表达式指定的一个或多个行,或由查询产生的零个或多个行。

目标列名可以按任何顺序列出。如果根本没有给出列名列表,则默认为表的所有列按其声明的顺序;或者前 N 个列名(如果仅由 VALUES 子句或 query 提供 N 个列)。由 VALUES 子句或 query 提供的值与显式或隐式列列表从左到右关联。

显式或隐式列列表中不存在的每一列都将填充默认值,即声明的默认值或(如果不存在)空值。

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

INSERT 进入缺少唯一索引的表不会被并发活动阻塞。如果并发会话执行锁定或修改与正在插入的唯一索引值匹配的行,则带有唯一索引的表可能会阻塞;详情请参阅第 64.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 子句。在这种情况下,可以在 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 的标识列,在未指定 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_expression

在插入或更新每行后,由 INSERT 命令计算并返回的表达式。该表达式可以使用由 table_name 命名的表中的任何列名。编写 * 以返回已插入或已更新行的所有列。

output_name

用于返回列的名称。

ON CONFLICT 子句

可选 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 结果;只要没有独立错误,即使在高并发下,这两个结果之一也得到保证。这也称为 UPSERTUPDATE 或 INSERT

conflict_target

指定 ON CONFLICT 通过选择 仲裁索引 来采取替代操作的冲突。执行 唯一索引推断,或显式命名约束。对于 ON CONFLICT DO NOTHING,指定 conflict_target 是可选的;省略时,将处理与所有可用约束(和唯一索引)的冲突。对于 ON CONFLICT DO UPDATEconflict_target 必须 提供。

conflict_action

conflict_action 指定一个替代 ON CONFLICT 操作。它可以是 DO NOTHING,或一个 DO UPDATE 子句,指定在发生冲突时要执行的 UPDATE 操作的确切详细信息。在 ON CONFLICT DO UPDATE 中,SETWHERE 子句可以使用表的名称(或别名)访问现有行,并使用特殊 excluded 表访问建议插入的行。SELECT 权限要求在目标表中读取相应 excluded 列的任何列上。

请注意,所有每行 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 约束和唯一索引作为仲裁器。

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

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

提示

通常,最好使用唯一索引推断,而不是使用 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');

此示例将一些行从表 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;

插入分销商,或者在现有、被排除的行(在行插入触发器触发后具有匹配的受约束列或列的行)存在时,对建议插入的行不执行任何操作。示例假设已定义唯一索引,该索引约束出现在 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 列中的值,其中 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 扩展,与 WITHINSERT 一起使用以及使用 ON CONFLICT 指定备用操作的能力一样。此外,标准不允许省略列名称列表但并非所有列都由 VALUES 子句或 query 填充的情况。如果您希望获得比 ON CONFLICT 更加符合 SQL 标准的语句,请参阅 MERGE

SQL 标准规定,仅当始终存在生成的身份列时,才能指定 OVERRIDING SYSTEM VALUE。PostgreSQL 在任何情况下都允许该子句,并在不适用时忽略它。

query 子句的可能限制在 SELECT 下有记录。