INSERT — 在表中创建新行
[ WITH [ RECURSIVE ]with_query
[, ...] ] INSERT INTOtable_name
[ ASalias
] [ (column_name
[, ...] ) ] [ OVERRIDING { SYSTEM | USER } VALUE ] { DEFAULT VALUES | VALUES ( {expression
| DEFAULT } [, ...] ) [, ...] |query
} [ ON CONFLICT [conflict_target
]conflict_action
] [ RETURNING { * |output_expression
[ [ AS ]output_name
] } [, ...] ] whereconflict_target
can be one of: ( {index_column_name
| (index_expression
) } [ COLLATEcollation
] [opclass
] [, ...] ) [ WHEREindex_predicate
] ON CONSTRAINTconstraint_name
andconflict_action
is one of: DO NOTHING DO UPDATE SET {column_name
= {expression
| DEFAULT } | (column_name
[, ...] ) = [ ROW ] ( {expression
| DEFAULT } [, ...] ) | (column_name
[, ...] ) = (sub-SELECT
) } [, ...] [ WHEREcondition
]
INSERT
将新行插入到表中。可以插入由值表达式指定的一个或多个行,或者插入由查询产生的零个或多个行。
目标列名可以以任何顺序列出。如果没有给出任何列名列表,则默认为表中所有列,按照它们声明的顺序;或者如果 VALUES
子句或 query
仅提供了 N
列,则为前 N
列名。VALUES
子句或 query
提供的值从左到右与显式或隐式列列表关联。
显式或隐式列列表中不存在的每个列都将填充默认值,要么是其声明的默认值,要么如果没有默认值则为 null。
如果任何列的表达式的数据类型不正确,将尝试自动类型转换。
对于缺少唯一索引的表,INSERT
不会被并发活动阻止。如果并发会话执行锁定或修改与要插入的唯一索引值匹配的行的操作,则具有唯一索引的表可能会被阻止;详细信息请参阅 第 62.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。
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 VALUE
或 OVERRIDING 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_action
。 ON 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
保证原子 INSERT
或 UPDATE
的结果;在没有独立错误的情况下,保证会产生这两种结果之一,即使在高并发情况下也是如此。这也称为 UPSERT — “更新或插入(UPDATE or INSERT)”。
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
中的 SET
和 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_name
或 index_expression
使用特定的排序规则,以便在推断期间进行匹配。通常省略此项,因为排序规则通常不影响是否发生约束违规。遵循 CREATE INDEX
格式。
opclass
指定后,强制相应的 index_column_name
或 index_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
是一个“确定性”语句。这意味着该命令将不允许一次影响任何单个现有行多次;当出现这种情况时,将引发基数违规错误。提议插入的行在仲裁器索引或约束约束的属性方面不应彼此重复。
请注意,当前不支持将应用于分区表的 INSERT
的 ON CONFLICT DO UPDATE
子句更新冲突行的分区键,以使其需要将该行移动到新的分区。
通常最好使用唯一索引推断,而不是使用 ON CONFLICT ON CONSTRAINT
constraint_name
直接命名约束。当底层索引被另一个或多或少等效的索引以重叠方式替换时,例如在使用 CREATE UNIQUE INDEX ... CONCURRENTLY
之前删除要替换的索引时,推断将继续正常工作。
成功完成后,INSERT
命令返回一个命令标记,其格式为
INSERToid
count
count
是插入或更新的行数。oid
始终为 0 (它曾经是OID如果 count
恰好为 1 且目标表被声明为 WITH OIDS
,则分配给插入行的 OID,否则为 0,但不再支持创建 WITH OIDS
表)。
如果 INSERT
命令包含一个 RETURNING
子句,则结果将类似于包含 RETURNING
列表中定义的列和值的 SELECT
语句,这些列和值是通过该命令插入或更新的行计算得出的。
如果指定的表是分区表,则每行都会被路由到相应的分区并插入到其中。如果指定的表是分区,则如果其中一个输入行违反了分区约束,则会发生错误。
您可能还希望考虑使用 MERGE
,因为它允许在单个语句中混合 INSERT
、UPDATE
和 DELETE
。请参阅 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');
此示例使用 date 列的 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;
如果可能,插入新的分销商;否则 DO NOTHING
。示例假设已定义了一个唯一索引,该索引约束了在 is_active
布尔列求值为 true
的行的子集中,出现在 did
列中的值
-- 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 下。
如果您发现文档中任何不正确、与您使用特定功能的体验不符或需要进一步澄清的地方,请使用 此表单 来报告文档问题。