是否可以在Postgres 8.1中更改列的自然顺序?
我知道你不应该依赖列顺序 - 它对我正在做的事情并不重要 - 我只需要它以一种更令人愉悦的方式制作一些自动生成的东西,以便字段顺序匹配所有从pgadmin通过后端到前端的方式.
小智 22
你实际上可以直接改变列顺序,但我几乎不推荐它,你应该非常小心,如果你决定这样做.
例如.
# 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可能会有所不同.
Tom*_*zky 16
如果您的数据库不是很大并且您可以承受一些停机时间,那么您可以:
pg_dump --create --column-inserts databasename > databasename.pgdump.sqlCREATE TABLEdatabasename.pgdump.sql中的适当语句split命令将其拆分,编辑,然后使用汇编回来catdrop database databasenamepsql --single-transaction -f databasename.pgdump.sql--single-transaction它会很慢如果使用所谓的大对象,请确保它们包含在转储中.我不确定它们是否默认为8.1.
我在2007年的pgsql-admin中提出了这个问题.Tom Lane本人宣称改变目录中的顺序实际上是不可行的.
澄清:对于用户,使用现有工具.不代表,它无法实施.IMO,它应该是.
对于Postgres 11来说仍然如此.
我也想要同样的。是的,顺序对于我的用例来说并不重要,但它只会让我烦恼:)
我正在采取的解决方法如下。
此方法将确保您保留任何现有数据,
当前表顺序:
id, name, email
Run Code Online (Sandbox Code Playgroud)
1. 使用临时名称,使用我想要的顺序创建新版本的表。
在这个例子中,我想email在 之前name。
CREATE TABLE mytable_tmp
(
id SERIAL PRIMARY KEY,
email text,
name text
);
Run Code Online (Sandbox Code Playgroud)
2. 将现有表中的所有数据插入到新表中。
INSERT INTO mytable_tmp --- << new tmp table
(
id
, email
, name
)
SELECT
id
, email
, name
FROM mytable; --- << this is the existing table
Run Code Online (Sandbox Code Playgroud)
3. 删除旧表。
DROP TABLE mytable;
Run Code Online (Sandbox Code Playgroud)
4. 将新表从“临时名称”重命名为“正确名称”。
ALTER TABLE mytable_tmp RENAME TO mytable;
Run Code Online (Sandbox Code Playgroud)
5. 重新添加您以前拥有的任何索引。
CREATE INDEX ...
Run Code Online (Sandbox Code Playgroud)
6. 重置主键增量的 ID 序列。
SELECT setval('public.mytable_id_seq', max(id)) FROM mytable;
Run Code Online (Sandbox Code Playgroud)
小智 5
您不能使用 postgres 就地更改列的顺序。但是,您可以通过视图解决您的问题。出于报告查询的目的,它看起来就像一个表格。就像是:
create view my_view as select * from my_table order by some_col;
Run Code Online (Sandbox Code Playgroud)
如果您的数据必须保持原位,您将不得不兼顾
您可以使用视图创建一个包含重新排序的列的新表,如下所示:
-- foo is the table you want to re-order columns in
drop table foo;
CREATE TABLE foo ( moo integer, bar character varying(10), baz date );
insert into foo (moo, bar, baz) values (34, 'yadz', now());
insert into foo (moo, bar, baz) values (12, 'blerp', now());
select * from foo;
????????????????????????????
? moo ? bar ? baz ?
????????????????????????????
? 34 ? yadz ? 2021-04-07 ?
? 12 ? blerp ? 2021-04-07 ?
????????????????????????????
-- Define your reordered columns here, don't forget one,
-- or it'll be missing from the replacement.
drop view if exists my_view;
create view my_view as ( select moo, baz, bar from foo );
select * from my_view;
DROP TABLE IF EXISTS foo2;
--foo2 is your replacement table that has columns ordered correctly
create table foo2 as select * from my_view;
select * from foo2;
--finally drop the view and the original table and rename
DROP VIEW my_view;
DROP TABLE foo;
ALTER TABLE foo2 RENAME TO foo;
select * from foo;
????????????????????????????
? moo ? baz ? bar ?
????????????????????????????
? 34 ? 2021-04-07 ? yadz ?
? 12 ? 2021-04-07 ? blerp ?
????????????????????????????
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
27176 次 |
| 最近记录: |