如何在 PostgreSQL 中指定新列的位置?

Jon*_*nas 106 postgresql database-design

如果我有一个包含列的表:

id | name | created_date
Run Code Online (Sandbox Code Playgroud)

并想添加一列,我使用:

alter table my_table add column email varchar(255)
Run Code Online (Sandbox Code Playgroud)

然后在列之后添加created_date列。

有什么办法可以指定新列的位置吗?例如,我可以在之后添加它name并得到一个表格,如:

id | name | email | created_date
Run Code Online (Sandbox Code Playgroud)

Mar*_*ian 75

ALTER TABLE ADD COLUMN只会在最后添加新列,作为最后一列。为了在另一个位置创建一个新列,您需要重新创建表并将旧表/当前表中的数据复制到这个新表中。

  • “[或通过添加列和旋转数据直到达到所需的布局](http://wiki.postgresql.org/wiki/Alter_column_position)” (18认同)
  • 没错。。但是真的有人用这个方法吗?:-) (4认同)
  • 如果它比重新创建表和所有 [子表](http://www.postgresql.org/docs/9.0/static/ddl-inherit.html)、外键和授权更容易:) 我认为链接可能是无论哪种方式都很有用,因为它解释了为什么不能指定位置并希望它可以在未来版本中实现。 (3认同)
  • @JackDouglas,8年后我可能会被迫使用这种确切的方法!爱你,伙计! (2认同)
  • 我想我对这个仍然有用的感觉很复杂!看起来在这方面取得进展的最新努力是 [2015 年](https://www.postgresql.org/message-id/flat/1185313031.785041.1424990529572.JavaMail.yahoo%40mail.yahoo.com#dc57f5bb07c301422507c3014820a你感兴趣的情况。 (2认同)
  • @JackDouglas - 它仍然认为它有用。我刚刚发现了这个线程,因为我正在制作几个新表的原型,并且希望这些列以我正在思考的方式出现(“哦 - 我发现我需要一个额外的列“这里””)。在快速原型设计中,我不想执行长选择查询或在 INSERT 中指定列顺序。此外,对于其他试图获取数据库的人来说,从简单的“\d”开始的自然或直观的列顺序可以在“自我文档”方面大有帮助——甚至可能是后来的你!:-) (2认同)

Sco*_*owe 26

如果您想要某个顺序,则需要重新创建表。只需执行以下操作:

alter table tablename rename to oldtable;
create table tablename (column defs go here);
insert into tablename (col1, col2, col3) select col2, col1, col3 from oldtable;
Run Code Online (Sandbox Code Playgroud)

根据需要创建索引等。


小智 6

如果你只是为了外观而想要这个,我发现为每个表保留一个具有所需列顺序的视图,并从中选择而不是表更容易。

create table my_table (
create view view_my_table as
  select id, name, created_date from my_table;

-- adding a new column
begin;
alter table my_table add column email varchar(255);
drop view view_my_table;
create view view_my_table as
  select id, name, email, created_date from my_table;
commit;
Run Code Online (Sandbox Code Playgroud)

对于所有其他目的(如插入、联合),最好始终指定列列表。

-- bad
insert into my_table values (...);
(select * from my_table)
  union all
(select * from my_table);

-- good
insert into my_table (id, name, email, created_date) values (...);
(select id, name, email, created_date from my_table)
  union all
(select id, name, email, created_date from my_table);
Run Code Online (Sandbox Code Playgroud)