题
它是能够改变的自然顺序列Postgres8.1?
我知道,你不应该依赖列顺序-不 重要 到我在做什么-我只需要做一些自动生成的东西出来的方式,更令人高兴,因此该领域以匹配,从pgadmin通过后端和出于前端。
解决方案
你实际上可以直接改变列顺序,但我几乎不推荐它,如果你决定这样做,你应该非常小心。
例如
# CREATE TABLE test (a int, b int, c int); # INSERT INTO test VALUES (1,2,3); # SELECT * FROM test; a | b | c ---+---+--- 1 | 2 | 3 (1 row)
现在对于棘手的问题,您需要使用postgres用户连接到您的数据库,以便您可以修改系统表。
# SELECT relname, relfilenode FROM pg_class WHERE relname='test'; relname | relfilenode ---------+------------- test_t | 27666 (1 row) # SELECT attrelid, attname, attnum FROM pg_attribute WHERE attrelid=27666; attrelid | attname | attnum ----------+----------+-------- 27666 | tableoid | -7 27666 | cmax | -6 27666 | xmax | -5 27666 | cmin | -4 27666 | xmin | -3 27666 | ctid | -1 27666 | b | 1 27666 | a | 2 27666 | c | 3 (9 rows)
attnum是一个唯一的列,因此在修改列号时需要使用临时值:
# UPDATE pg_attribute SET attnum=4 WHERE attname='a' AND attrelid=27666; UPDATE 1 # UPDATE pg_attribute SET attnum=1 WHERE attname='b' AND attrelid=27666; UPDATE 1 # UPDATE pg_attribute SET attnum=2 WHERE attname='a' AND attrelid=27666; UPDATE 1 # SELECT * FROM test; b | a | c ---+---+--- 1 | 2 | 3 (1 row)
同样,因为这是在使用数据库系统表,所以如果您觉得确实需要这样做,请格外小心。
这与postgres 8.3一样,对于以前的版本,你的milage可能会有所不同。
其他提示
如果您的数据库不是很大并且您可以承受一些停机时间,那么您可以:
- 禁用对数据库的写访问权限 这是必不可少的,否则在开始下一个点之后的任何更改都将丢失
-
pg_dump --create --column-inserts databasename> databasename.pgdump.sql 代码>
- 在databasename.pgdump.sql中编辑适当的
CREATE TABLE
语句 如果文件对于编辑器来说太大,只需使用split
命令将其拆分,编辑,然后使用cat
进行汇编。
-
drop database databasename
你有最近的备份,为了以防万一,是吗? -
psql --single-transaction -f databasename.pgdump.sql
如果您不使用- 单一事务
,那将会很慢
醇>
如果使用所谓的大对象,请确保它们包含在转储中。我不确定它们是否默认为8.1。
我问这个问题在pgsql管理员在2007年。汤姆的车道自己宣布,它实际上是不可行的改变秩序的目录。
澄清:对于用户使用,与本工具。并不意味着它就不可能实现的。海事组织,它应该是。
仍然真正Postgres11.
正如提到的其他答案,你不能改变列的顺序,这取决于postgres。您可以(并且应该!)通过视图解决您的问题。出于报告查询的目的,它看起来就像一个表。类似的东西:
create view my_view as
select * from my_table
order by some_col;
在查询中指定列顺序是唯一可靠(且理智)的方式。也就是说,通常可以通过更改表来获得不同的排序,如下例所示,因为列通常(不保证)按照它们添加到表中的顺序返回。
postgres=# create table a(a int, b int, c int);
CREATE TABLE
postgres=# insert into a values (1,2,3);
INSERT 0 1
postgres=# select * from a;
a | b | c
---+---+---
1 | 2 | 3
(1 row)
postgres=# alter table a add column a2 int;
ALTER TABLE
postgres=# select * from a;
a | b | c | a2
---+---+---+----
1 | 2 | 3 |
(1 row)
postgres=# update a set a2 = a;
UPDATE 1
postgres=# alter table a drop column a;
ALTER TABLE
postgres=# alter table a rename column a2 to a;
ALTER TABLE
postgres=# select * from a;
b | c | a
---+---+---
2 | 3 | 1
(1 row)
postgres=#
不幸的是,不,不是。列顺序完全取决于Postgres。
您可以通过创建新表并按照希望它们显示的顺序选择旧表的列来获取所需的列顺序:
CREATE TABLE test_new AS SELECT b, c, a FROM test;
SELECT * from test_new;
b | c | a
---+---+---
2 | 3 | 1
(1 row)
请注意,这仅复制数据,而不是修饰符,约束,索引等。
按照您想要的方式修改新表后,删除原始表并更改新表的名称:
BEGIN;
DROP TABLE test;
ALTER TABLE test_new RENAME TO test;
COMMIT;
我也想要一样。是的,现在订购它是必不可少的,但它只是以错误的方式揉我:)
我正在做的解决方法如下。
此方法将确保您保留所有现有数据
- 使用临时名称,使用我想要的顺序创建表的新版本。
- 将所有数据从现有数据插入到新表中。
- 放下旧桌子。
- 将新表重命名为“专有名称”来自“临时名称”。
- 重新添加您之前拥有的任何索引。
- 重置主键增量的ID序列。 醇>
当前的表格顺序:
id, name, email
<强> 1。使用我想要的顺序使用临时名称创建表的新版本。
在这个例子中,我希望 email
在 name
之前。
CREATE TABLE mytable_tmp
(
id SERIAL PRIMARY KEY,
email text,
name text
);
<强> 2。将所有数据从现有数据插入到新表中。
INSERT INTO mytable_tmp --- << new tmp table
(
id
, email
, name
)
SELECT
id
, email
, name
FROM mytable; --- << this is the existing table
第3。放下旧桌子。
DROP TABLE mytable;
<强> 4。将新表重命名为“专有名称”来自“临时名称”。
ALTER TABLE mytable_tmp RENAME TO mytable;
<强> 5。重新添加您之前拥有的任何索引。
CREATE INDEX ...
<强> 6。重置主键增量的ID序列。
SELECT setval('public.mytable_id_seq', max(id)) FROM mytable;