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

StackOverflow https://stackoverflow.com/questions/126430

  •  02-07-2019
  •  | 
  •  

Вопрос

Можно ли изменить естественный порядок столбцов в Postgres 8.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, в предыдущих версиях ваш пробег может отличаться.

Другие советы

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

  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.

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

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

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

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;

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

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

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

  1. Создайте новую версию таблицы, используя нужный мне порядок, используя временное имя.
  2. Вставьте в эту новую таблицу все данные из существующей.
  3. Отбросьте старую таблицу.
  4. Переименуйте новую таблицу в "собственное имя" из "временного имени".
  5. Повторно добавьте все индексы, которые у вас были ранее.
  6. Сбросьте последовательность идентификаторов для приращений первичного ключа.

Текущий порядок расположения столов:

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.Сбросьте последовательность идентификаторов для приращений первичного ключа.

SELECT setval('public.mytable_id_seq', max(id)) FROM mytable;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top