Можно ли изменить естественный порядок столбцов в Postgres? - PullRequest
22 голосов
/ 24 сентября 2008

Можно ли изменить естественный порядок столбцов в Postgres 8.1?

Я знаю, что вы не должны полагаться на порядок столбцов - это не важно для того, что я делаю - мне нужно только, чтобы некоторые автоматически сгенерированные вещи получались более приятными , так что порядок полей совпадает на всем пути от pgadmin через задний конец и до внешнего конца.

Ответы [ 8 ]

20 голосов
/ 18 марта 2009

На самом деле вы можете просто изменить порядок столбцов, но я бы вряд ли это порекомендовал, и вы должны быть очень осторожны, если решите это сделать.

например.

# 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, в предыдущих версиях ваш пробег может отличаться.

16 голосов
/ 24 сентября 2008

Если ваша база данных не очень большая, и вы можете позволить себе некоторое время простоя, то вы можете:

  1. Отключить доступ на запись в базу данных
    это важно, так как в противном случае любые изменения после начала следующей точки будут потеряны
  2. pg_dump --create --column-inserts databasename > databasename.pgdump.sql
  3. Редактировать соответствующий CREATE TABLE оператор в databasename.pgdump.sql
    Если файл слишком велик для вашего редактора, просто разбейте его с помощью команды split, отредактируйте, а затем соберите обратно, используя cat
  4. drop database databasename
    У вас есть недавняя резервная копия, на всякий случай?
  5. psql --single-transaction -f databasename.pgdump.sql
    Если вы не используете --single-transaction, это будет очень медленно

Если вы используете так называемые крупные объекты, убедитесь, что они включены в дамп. Я не уверен, что они по умолчанию в 8.1.

7 голосов
/ 16 сентября 2011

Я задал этот вопрос в pgsql-admin в 2007 году. Сам Том Лейн объявил, что практически невозможно изменить порядок в каталогах.

Разъяснение: для пользователей, с настоящими инструментами. Это не значит, что это не может быть реализовано. ИМО, так и должно быть.
Все еще верно для Postgres 11.

4 голосов
/ 24 сентября 2008

Как уже упоминалось в других ответах, вы не можете изменить порядок столбцов, это зависит от postgres. Вы можете (и должны!) Решить вашу проблему с целью. В целях вашего отчета о запросах он будет выглядеть как таблица. Что-то вроде:

create view my_view as
  select * from my_table
  order by some_col;
1 голос
/ 24 сентября 2008

Указание порядка столбцов в запросе является единственным надежным (и вменяемым) способом . Тем не менее, обычно вы можете получить другой порядок, изменив таблицу, как показано в примере ниже, так как столбцы обычно (не гарантированно) возвращаются в порядке их добавления в таблицу.

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=#
0 голосов
/ 02 февраля 2018

Я хочу того же. Да, заказывайте сейчас обязательно, но это меня просто теряет :):

Что я делаю, чтобы решить это следующим образом.

Этот метод гарантирует, что вы СОХРАНИТЕ любые существующие данные,

  1. Создайте новую версию таблицы, используя нужный порядок, используя временное имя.
  2. Вставить все данные в эту новую таблицу из существующей.
  3. Оставь старый стол.
  4. Переименуйте новую таблицу в «собственное имя» из «временного имени».
  5. Повторно добавьте все индексы, которые у вас были ранее.
  6. Сброс последовательности 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;
0 голосов
/ 01 декабря 2016

Вы можете получить нужный порядок столбцов, создав новую таблицу и выбрав столбцы старой таблицы в том порядке, в котором вы хотите их представить:

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;
0 голосов
/ 24 сентября 2008

К сожалению, нет, это не так. Порядок столбцов полностью зависит от Postgres.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...