# 插入

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 ]

# 描述

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

目标列名称可以按任何顺序列出。如果根本没有给出列名列表,则默认为按声明顺序排列的表的所有列;或第一个*ñ列名,如果只有ñ由提供的列价值观条款或询问.提供的值价值观条款或询问*与从左到右的显式或隐式列列表相关联。

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

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

关于冲突可用于指定引发唯一约束或排除约束违规错误的替代操作。(看冲突条款以下。)

可选的返回条款原因插入根据实际插入(或更新,如果冲突时做更新使用了子句)。这主要用于获取默认提供的值,例如序列号。但是,任何使用表列的表达式都是允许的。的语法返回列表与输出列表的列表相同选择.只会返回成功插入或更新的行。例如,如果一行被锁定但没有更新,因为ON CONFLICT DO UPDATE ...在哪里条款*(健康)状况*不满意,该行将不予退还。

你必须有插入表上的特权,以便插入其中。如果冲突时做更新存在,更新还需要对表的特权。

如果指定了列列表,则只需要插入列出列的权限。同样,当冲突时做更新是指定的,你只需要更新列出要更新的列的权限。然而,冲突时做更新还需要选择对其值在冲突时做更新表达式或*(健康)状况*.

的使用返回子句要求选择中提到的所有列的特权返回.如果您使用*询问*子句从查询中插入行,你当然需要有选择查询中使用的任何表或列的特权。

# 参数

# 插入

本节介绍仅在插入新行时可能使用的参数。参数关于冲突条款单独描述。

with_query

子句允许您指定一个或多个子查询,这些子查询可以在插入询问。看第 7.8 节选择详情。

这是可能的*询问(选择声明)也包含一个条款。在这种情况下,两组with_query可以参考内询问*,但第二个优先,因为它嵌套得更紧密。

表名

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

别名

的替代名称*表名*.提供别名时,它会完全隐藏表的实际名称。这在以下情况下特别有用冲突时做更新定位一个名为的表排除在外, 因为否则将被视为表示建议插入的行的特殊表的名称。

列名

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

压倒一切的系统价值

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

对于定义为的标识列始终生成,插入显式值是错误的(除了默认) 没有指定压倒一切的系统价值或者压倒一切的用户价值.(对于定义为的标识列默认生成,压倒一切的系统价值是正常行为并且指定它什么都不做,但 PostgreSQL 允许它作为扩展。)

压倒一切的用户价值

如果指定了此子句,则为标识列提供的任何值都将被忽略,并应用默认的序列生成值。

例如,在表之间复制值时,此子句很有用。写作插入到 tbl2 覆盖用户值选择 * 从 tbl1将从表1不是身份列的所有列表2而身份列的值表2将由与相关的序列生成表2.

默认值

所有列都将填充它们的默认值,就像默认为每一列明确指定。(一个压倒一切此表格中不允许有子句。)

表达

要分配给相应列的表达式或值。

默认

相应的列将填充其默认值。标识列将填充由相关序列生成的新值。对于生成的列,允许指定这一点,但仅指定从其生成表达式计算列的正常行为。

询问

一个问题 (选择语句)提供要插入的行。请参阅选择用于描述语法的语句。

输出表达式

要计算并返回的表达式插入插入或更新每一行后的命令。表达式可以使用名为的表的任何列名*表名*.写*返回插入或更新行的所有列。

输出名称

用于返回列的名称。

# 关于冲突条款

可选的关于冲突子句指定引发唯一违规或排除约束违规错误的替代操作。对于建议插入的每个单独的行,插入继续进行,或者,如果仲裁者由指定的约束或索引*冲突目标被违反,替代方案冲突动作*被采取。在冲突中什么都不做只是避免插入一行作为其替代操作。冲突时做更新更新与建议插入的行冲突的现有行作为其替代操作。

冲突目标可以执行唯一索引推断.在进行推理时,它由一个或多个*index_column_name列和/或索引表达式表达式和一个可选的索引谓词.全部表名唯一索引,不考虑顺序,完全包含冲突目标- 指定的列/表达式被推断(选择)为仲裁索引。如果索引谓词*作为推理的进一步要求,它必须满足仲裁器索引。请注意,这意味着将推断出非部分唯一索引(没有谓词的唯一索引)(因此由关于冲突) 如果存在满足所有其他标准的此类索引。如果推理尝试不成功,则会引发错误。

冲突时做更新保证原子插入或者更新结果;如果没有独立错误,即使在高并发下,也可以保证这两种结果之一。这也被称为UPSERT— “更新或插入”。

冲突目标

指定哪些冲突关于冲突通过选择采取替代行动仲裁索引.要么执行唯一索引推断,或显式命名约束。为了在冲突中什么都不做, 可以选择指定一个*冲突目标;省略时,将处理与所有可用约束(和唯一索引)的冲突。为了冲突时做更新, 一种冲突目标* 必须提供。

冲突动作

*冲突动作*指定替代方案关于冲突行动。它可以是没做什么, 或做更新条款指定的确切细节更新发生冲突时要执行的操作。这在哪里中的子句冲突时做更新可以使用表的名称(或别名)访问现有行,并使用特殊的访问建议插入的行排除在外桌子。选择目标表中对应的任何列都需要特权排除在外列被读取。

请注意,所有每行的效果插入前触发器反映在排除在外值,因为这些影响可能导致该行被排除在插入之外。

index_column_name

一个名字*表名柱子。用于推断仲裁器索引。关注创建索引格式。选择特权index_column_name*是必须的。

索引表达式

如同*index_column_name, 但用于推断表达式表名出现在索引定义中的列(不是简单的列)。关注创建索引格式。选择对出现在其中的任何列的特权索引表达式*是必须的。

整理

指定时,要求相应的*index_column_name或者索引表达式*使用特定的排序规则以便在推理期间进行匹配。通常这会被省略,因为排序规则通常不会影响是否发生约束冲突。关注创建索引格式。

操作类

指定时,要求相应的*index_column_name或者索引表达式使用特定的运算符类以便在推理期间进行匹配。通常这会被省略,因为平等*无论如何,语义通常在类型的运算符类中是等价的,或者因为足以相信定义的唯一索引具有相关的相等定义。关注创建索引格式。

索引谓词

用于允许推断部分唯一索引。可以推断满足谓词的任何索引(实际上不必是部分索引)。关注创建索引格式。选择对出现在其中的任何列的特权*索引谓词*是必须的。

约束名

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

健康)状况

返回类型值的表达式布尔值.仅此表达式返回的行真的将被更新,虽然所有行都将被锁定时冲突时做更新采取行动。注意*健康)状况*在将冲突确定为要更新的候选者之后,最后评估。

请注意,不支持排除约束作为仲裁者冲突时做更新.在所有情况下,只有不可延期支持约束和唯一索引作为仲裁器。

插入冲突时做更新子句是“确定性”语句。这意味着该命令将不允许多次影响任何单个现有行;出现这种情况时将引发基数违规错误。建议插入的行不应在受仲裁索引或约束约束的属性方面相互重复。

请注意,目前不支持冲突时做更新一个子句插入应用于分区表以更新冲突行的分区键,从而需要将该行移动到新分区。

# 提示

通常最好使用唯一索引推断,而不是直接使用命名约束关于约束的冲突 约束名.当基础索引以重叠方式被另一个或多或少等效的索引替换时,推理将继续正常工作,例如使用创建唯一索引...并发在删除要替换的索引之前。

# 输出

成功完成后,插入命令返回形式的命令标签

INSERT oid count

这*数数是插入或更新的行数。样的始终为 0(它曾经是分配给插入行的 OID,如果数数*正好是 1,并且声明了目标表与 OIDS否则为 0,但创建一个表与 OIDS不再支持)。

如果插入命令包含一个返回子句,结果将类似于选择包含在返回列表,根据命令插入或更新的行计算。

# 笔记

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

# 例子

在表格中插入一行电影

INSERT INTO films VALUES
    ('UA502', 'Bananas', 105, '1971-07-13', 'Comedy', '82 minutes');

在这个例子中,列被省略,因此它将具有默认值:

INSERT INTO films (code, title, did, date_prod, kind)
    VALUES ('T_601', 'Yojimbo', 106, '1961-06-16', 'Drama');

本示例使用默认日期列的子句而不是指定值:

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;

使用 multirow 插入多行价值观句法:

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具有相同的列布局电影

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," "}}');

在表格中插入一行经销商,返回由生成的序列号默认条款:

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;

根据需要插入或更新新的分销商。假设已经定义了一个唯一索引来限制出现在做过柱子。请注意,特殊的排除在外table 用于引用最初建议插入的值:

INSERT INTO distributors (did, dname)
    VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc')
    ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname;

插入分配器,或者当现有的排除行(在行插入触发器触发之前具有匹配的约束列或列的行)存在时,对建议插入的行不执行任何操作。示例假设已定义一个唯一索引,该索引限制出现在做过柱子:

INSERT INTO distributors (did, dname) VALUES (7, 'Redline GmbH')
    ON CONFLICT (did) DO NOTHING;

根据需要插入或更新新的分销商。示例假设已定义一个唯一索引,该索引限制出现在做过柱子。在哪里子句用于限制实际更新的行(但任何未更新的现有行仍将被锁定):

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

如果可能,插入新的分配器;否则没做什么.示例假设已定义一个唯一索引,该索引限制出现在做过行子集上的列,其中活跃布尔列计算为真的

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

# 兼容性

插入符合 SQL 标准,除了返回子句是 PostgreSQL 扩展,使用的能力也是如此插入,以及指定替代操作的能力关于冲突.此外,省略列名列表但并非所有列都从价值观条款或*询问*, 标准不允许。

SQL 标准规定压倒一切的系统价值仅当生成的标识列始终存在时才能指定。PostgreSQL 在任何情况下都允许该子句,如果它不适用则忽略它。

可能的限制*询问*条款记录在选择.