# 插入
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 在任何情况下都允许该子句,如果它不适用则忽略它。
可能的限制*询问
*条款记录在选择.