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。query(SELECT语句)也有可能包含WITH子句。在这种情况下,可以在query中引用两组with_query,但第二个子句优先,因为它嵌套得更紧密。table_name现有表的名称(可选,可以限定架构)。
aliastable_name的替代名称。提供别名后,它将完全隐藏表的实际名称。当ON CONFLICT DO UPDATE针对名为excluded的表时,这特别有用,因为否则会将该表视为表示拟插入行的特殊表的名称。column_nametable_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 或 INSERT”。
conflict_target指定
ON CONFLICT通过选择 仲裁索引 来采取替代操作的冲突。执行 唯一索引推断,或显式命名约束。对于ON CONFLICT DO NOTHING,指定conflict_target是可选的;省略时,将处理与所有可用约束(和唯一索引)的冲突。对于ON CONFLICT DO UPDATE,conflict_target必须 提供。conflict_actionconflict_action指定一个替代ON CONFLICT操作。它可以是DO NOTHING,或一个DO UPDATE子句,指定在发生冲突时要执行的UPDATE操作的确切详细信息。在ON CONFLICT DO UPDATE中,SET和WHERE子句可以使用表的名称(或别名)访问现有行,并使用特殊excluded表访问建议插入的行。SELECT权限要求在目标表中读取相应excluded列的任何列上。请注意,所有每行
BEFORE INSERT触发器的效果都反映在excluded值中,因为这些效果可能导致将行排除在插入之外。index_column_nametable_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命令将返回以下形式的命令标记
INSERT oid count*count是插入或更新的行数。oid始终为 0(如果count*正好为 1 且目标表声明为WITH OIDS,则它曾经是分配给插入行的OID,否则为 0,但不再支持创建WITH OIDS表)。
如果INSERT命令包含RETURNING子句,则结果将类似于SELECT语句,其中包含RETURNING列表中定义的列和值,这些列和值是通过该命令插入或更新的行计算得出的。
说明
如果指定表是分区表,则每行都将路由到适当的分区并插入其中。如果指定表是分区,则如果输入行之一违反分区约束,则会发生错误。
您可能还想考虑使用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');此示例对日期列使用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扩展,与WITH与INSERT一起使用以及使用ON CONFLICT指定备用操作的能力一样。此外,标准不允许省略列名称列表但并非所有列都由VALUES子句或*query*填充的情况。如果您希望获得比ON CONFLICT更加符合 SQL 标准的语句,请参阅MERGE。
SQL 标准规定,仅当始终存在生成的身份列时,才能指定OVERRIDING SYSTEM VALUE。PostgreSQL 在任何情况下都允许该子句,并在不适用时忽略它。
*query*子句的可能限制在SELECT下有记录。
