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

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提供的值从左到右与显式或隐式列列表相关联。

显式或隐式列列表中不存在的每个列都将填充默认值,可能是其声明的默认值,如果没有则为 null。

如果任意列的表达式的类型不正确,系统将会尝试自动转换类型。

INSERT到没有唯一索引的表中不会因并发活动而阻塞。如果有唯一索引的表可能会在并发会话执行锁定或修改与正在插入的唯一索引值匹配的行时发生阻塞;详细信息介绍于第 62.5 节。可以使用ON CONFLICT指定替代动作以引发唯一约束或排除约束冲突错误。(参见下文的ON CONFLICT 子句。)

可选的RETURNING子句让INSERT根据实际上插入(或 updated,如果使用了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

query (SELECT 语句)也有可能包含 WITH 子句。在这种情况下,两种 with_query 可以在 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 指定的调停符约束或索引被违反,则执行备用onflict_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

冲突_动作指定备用ON CONFLICT 动作。它可以是不执行任何操作,也可以是指定在发生冲突时执行的UPDATE 操作的准确详细信息的执行更新 子句。SETWHERE 子句在ON CONFLICT DO UPDATE 中可以使用表的名称(或别名)访问现有行,并使用特殊excluded 表访问建议插入的行。SELECT 权限是该相应excluded 列读取的目标表的任何列都所必需的。

请注意,所有逐行BEFORE INSERT 触发器的效果都反映在excluded 值中,因为这些效果可能导致该行被排除在插入之外。

index_column_name

table_name列的名称。用于推断仲裁索引。遵循CREATE INDEX 格式。SELECT 权限对index_column_name 是必需的。

index_expression

类似于index_column_name,但用于推断出现在索引定义(而不是简单列)中的table_name列上的表达式。遵循CREATE INDEX 格式。SELECT 权限对出现在index_expression中的任何列都是必需的。

排序规则

指定时,要求相应的index_column_nameindex_expression 在推断期间使用特定排序规则才能进行匹配。通常会省略这一点,因为排序规则通常不会影响是否发生约束冲突。遵循CREATE INDEX 格式。

opclass

指定时,要求相应的index_column_nameindex_expression 在推断期间使用特定运算符类才能进行匹配。通常会省略这一点,因为无论如何,相等 语义通常在某个类型的运算符类之间是等效的,或因为相信已定义的唯一索引具有相等性的相关定义就足够了。遵循CREATE INDEX 格式。

index_predicate

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

constraint_name

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

条件

返回类型为 boolean 的表达式。仅当表达式返回 true 时,才会更新行,尽管在执行 ON CONFLICT DO UPDATE 操作时,所有行都将被锁定。请注意,条件 在将冲突识别为更新候选之后最后进行评估。

请注意,不支持将排除约束作为使用 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 是已插入或已更新的行数。如果 count 恰好为 1,且目标表声明为 WITH OIDS,则 oid 始终为 0(以前分配给已插入行,且 0 表示其他情况,但不再支持创建 WITH OIDS 表)。OID分配给已插入行,如果 count 恰好为 1,且目标表声明为 WITH OIDS,则 0 表示其他情况,但不再支持创建 WITH OIDS 表)。

如果 INSERT 命令包含一个 RETURNING 子句,结果将与一个 SELECT 语句类似,该语句包含 RETURNING 列表中定义的列和值,这些值计算自该命令插入或更新的行。

备注

如果指定表是分区表,则每行都将路由到适当的分区并插入其中。如果指定表是一个分区,则如果输入行之一违反分区约束,将会发生错误。

您可能还想考虑使用 MERGE,因为它允许在单一语句中混合 INSERTUPDATEDELETE。请参见 MERGE

示例

将单行插入到表 film

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');

此示例从具有与 film 相同列布局的表 tmp_film 中向表 film 中插入一些行

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;

如果可能,插入新的分销商;否则 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 下。