当从两个不同的服务器检索时,PHP中不同的PostgreSQL字段顺序


Different PostgreSQL fields orders in PHP when retrieved from two different servers

我使用CodeIgniter 2.1.3和PHP 5.4.8,以及两个PostgreSQL服务器(P1和P2)。

我在CodeIgniter中遇到list_fields()函数的问题。当我从P1服务器检索字段时,字段是按照最初创建表的顺序排列的。但是,如果我使用完全相同的代码从P2服务器检索字段,则字段的顺序是相反的。

如果字段从P1是array('id', 'name', 'age')

字段从P2变成array('age', 'name', 'id')

我不认为这是CodeIgniter特定的问题,而是一般的数据库配置或PHP问题,因为代码是相同的。

这是我获取字段的代码。

$fields = $this->db->list_fields("clients");

我必须澄清一些事情。@muistooshort在上面的评论中声明:

从技术上讲,表中的列没有定义顺序。

@mu可能考虑的是顺序或行,这是任意的,没有ORDER BY

对于列的顺序是完全不正确的,是定义良好的并存储在列pg_attribute.attnum中。它在许多地方使用,如INSERT没有列定义列表或SELECT *。它在转储/恢复周期中被保留,并且对存储大小和性能有重要影响。

在PostgreSQL中,你不能简单地改变列的顺序,因为它还没有实现。它深深根植于系统之中,很难改变。有一个Postgres Wiki页面,它在项目的TODO列表中:

允许通过记录显示、存储和每个列的永久id ?

Find out for your table:

SELECT attname, attnum
FROM   pg_attribute 
WHERE  attrelid = 'myschema.mytable'::regclass
AND    NOT attisdropped  -- no dropped (dead) columns
AND    attnum > 0        -- no system columns
ORDER  BY attnum;

某些上下文中使用SELECT *是不明智的,在这些上下文中,底层表的列可能会改变并破坏您的代码。在其他需要所有列(按默认顺序)的上下文中使用SELECT *显式明智的

关于第一个问题

不应该发生这种情况。SELECT *在PostgreSQL中以定义良好的顺序返回列。

我怀疑你已经习惯了MySQL,它允许你在表创建后重新排序列。PostgreSQL不允许你这样做,所以当你:

ALTER TABLE foo ADD bar int;

它把这个放在表的末尾总是并且没有办法改变顺序。

在PostgreSQL上,你不应该假设列的顺序是有意义的,因为根据列定义的顺序,这些顺序可能因服务器而异。

然而,这对我来说是奇怪的。

如果您想查看数据库上的预期顺序,请使用:

'd foo 
从psql

如果这些是相反的,那么问题是在数据库的创建(这是我的第一印象)。这是首先要看的。如果这还没有显示出问题,那么CodeIgniter就真的有点奇怪了。