首页 > 解决方案 > 带有 SELECT 排序的 Postgres INSERT INTO

问题描述

通过语句插入 Postgres 时select,是否保证以与 select 语句返回它们的顺序相同的顺序插入行?

也就是说,给定一个表bar(其中idisSERIAL PRIMARY KEYnameis TEXT):

id | name
---+-----
 0 | A
 1 | B
 2 | C

如果我保证有另一个表foo(空且具有相同的模式):INSERT INTO foo (name) SELECT name FROM bar ORDER BY id DESCfoo

id | name
---+-----
 0 | C
 1 | B
 2 | A

情况似乎如此,但我想确认它不是一个可能不适用于较大选择的实现细节。

我通读了SQL-92 标准和一般规则 #3 中的第 13.8 节,声称“在将任何行插入 B 之前有效地评估了查询表达式”,但它没有明确说明任何关于排序的内容。标准是否故意含糊不清(也许允许并行插入?)并且排序是实现细节?

标签: sqlpostgresql

解决方案


我在 Postgres 邮件列表上询问过,他们有助于澄清。事实证明,这是一个特定于数据库的答案,因此如果您正在阅读此内容并使用不同的数据库,答案可能不一样。

从 9.6 开始,Postgres 将在逻辑上按照返回的结果集的顺序插入。

该行为在此提​​交中明确编码:https ://github.com/postgres/postgres/commit/9118d03a8cca3d97327c56bf89a72e328e454e63

从提交描述:

例如,在 SELECT x 中,nextval('seq') FROM tab ORDER BY x LIMIT 10; 可能希望 nextval() 值的排序与 x 相同,并且 nextval() 运行次数不超过 10 次。

过去,Postgres 在这方面是不一致的:如果排序是通过 indexscan 执行的,您将获得理想的行为,但如果必须通过显式排序步骤完成,则不会。

tl;博士; 插入顺序是一个实现细节,但在 Postgres 9.6 及更高版本中有意编码以符合直觉。在 9.6 之前,没有任何保证。


推荐阅读