Postgres是否保留记录的插入顺序?


19

例如,当我使用返回记录ID的查询时

INSERT INTO projects(name)
VALUES (name1), (name2), (name3) returning id;

哪个产生输出:

1
2
3

此ID是否指向相应的插入值?

1 -> name1
2 -> name2
3 -> name3

4
除了实际的答案(我认为不是)之外,您不应依赖查询中指定的其他顺序。
dezso

Answers:


17

这个简单案例的答案是肯定的。在VALUES表达式中按提供的顺序插入行。而且,如果您的id列是serial类型,则将按该顺序从基础序列中获取值。

但这是一个实现细节,不能保证。特别是,在具有WHERE条件或联接的更复杂的查询中不一定要保留顺序。

如果同时进行的事务同时写入同一张表,则可能还会混入间隙或其他行。不太可能,但可能。

数据库表中没有“自然”顺序。尽管行的物理顺序(反映在系统列中ctid)最初将与它们的插入顺序相对应,但随时可能会改变。UPDATEDELETEVACUUM和其他命令可以改变行的物理顺序。但是,生成的值id是稳定的,并且与它毫无关系。


我认为Sergey所指的问题是第一行是否始终将id = 1,第二个id = 2,第三个id = 3-而不是实际的“订单”或行
a_horse_with_no_name

@a_horse_with_no_name:要回答这个问题:刚创建的serial列就是这种情况-理想情况下是在同一事务中。
Erwin Brandstetter

如果问题是“ name3的ID总是大于name1的ID”,那么它总是正确吗?(关于您的第二段)
卢拉拉拉

@lulalala:不一定适用于具有联接和WHERE条件的更复杂的查询。尽管我无法想到WHERE会改变行顺序的简单条件,但联接当然可以做到这一点。
Erwin Brandstetter

3

在某些情况下,Erwin Brandstetter的回答可能不正确。

我们已经完成了一项操作,INSERT INTO ... SELECT bar,baz FROM foo ORDER BY bar 并且看到 SELECT ctid,* FROM foo 显示表中行的物理顺序与插入顺序不完全匹配的情况,似乎有点儿混乱了。请注意,我们的表有一个jsonb列,其数据大小高度可变。在插入期间实验性地截断jsonb数据会导致插入顺序正确。


3
正如@Erwin第一句中指出的那样,他只是在问题中提到的特定单个实例中说“是”。正如@deszo在评论中所说,永远不要依赖“插入”顺序。如果出于任何目的依赖该顺序,则应始终在select语句中指定该顺序。
Max Vernon
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.