Как изменить положение столбца в таблице базы данных PostgreSQL?

Ответы:

107

« Изменить позицию столбца » в PostgreSQL Wiki говорит:

PostgreSQL в настоящее время определяет порядок столбцов на основе attnumстолбца pg_attributeтаблицы. Единственный способ изменить порядок столбцов - либо воссоздать таблицу, либо добавить столбцы и повернуть данные, пока не достигнете желаемого макета.

Это довольно слабо, но в их защиту в стандартном SQL тоже нет решения для изменения положения столбца. Бренды баз данных, которые поддерживают изменение порядкового номера столбца, определяют расширение синтаксиса SQL.

Мне пришла в голову еще одна идея: вы можете определить, VIEWкоторый определяет порядок столбцов, как вам нравится, без изменения физического положения столбца в базовой таблице.

Билл Карвин
источник
3
@ Дана: Я думаю, это то, что подразумевается под «воссозданием таблицы» в статье вики.
Билл Карвин,
2
'dump the database' :: отличный способ испортить данные. и, следовательно, эффект «очистки массивной базы данных».
Кент Фредрик
31
@Kent: Сомнительно, разработчики postgres проделали долгий путь, чтобы обеспечить согласованность данных, и это, безусловно, применимо к pg_dump. В конце концов, какой смысл делать резервные копии db, если восстановление не выполнено?
Dana the Sane
@Dana, да, но вы добавляете 1) большой процесс для сброса, а затем вы отбрасываете, и тогда у вас появляется большая трудоемкая нагрузка. Если у вас очень массивная база данных, что обычно бывает с 37 столбцами, вы рискуете заблокировать дисковый ввод-вывод.
Кент Фредрик
@DanatheSane, это супер старые комментарии, но то, что говорил Билл, по сути то же самое, вместо того, чтобы делать полный дамп базы данных, вы просто сбрасываете таблицу (и зависимости), уничтожаете оригинал, а затем воссоздаете. Нет необходимости отключать всю базу данных или тратить время на воссоздание чего-то, что не затронуто. С другой стороны, если есть много зависимостей, я обнаружил, что сделать полный дамп (как вы предложили) намного проще.
vol7ron 07
38

В PostgreSQL при добавлении поля оно будет добавлено в конец таблицы. Если нам нужно вставить в определенную позицию, тогда

alter table tablename rename to oldtable;
create table tablename (column defs go here);
insert into tablename (col1, col2, col3) select col1, col2, col3 from oldtable;
Allwin
источник
4
Вау, это здорово, я уверен, что это должен быть принятый ответ!
Tommaso Thea Cioni
Да, это действительно полезно, большое спасибо!
Акуна,
Вы также можете скопировать текущую таблицу в новую старую таблицу следующим образом: CREATE TABLE oldtable AS SELECT * FROM tablename;
Райан
29

Этот пост старый и, вероятно, решен, но у меня была та же проблема. Я решил эту проблему, создав представление исходной таблицы, указав новый порядок столбцов.

Отсюда я мог либо использовать представление, либо создать новую таблицу из представления.

    СОЗДАТЬ ПРОСМОТР original_tab_vw AS
    ВЫБЕРИТЕ a.col1, a.col3, a.col4, a.col2
    FROM original_tab a
    ГДЕ a.col1 НЕ НУЛЕВО - или что угодно
    ВЫБРАТЬ * В новую_таблицу ИЗ исходной_таблицы

Переименуйте или удалите исходную таблицу и задайте имя новой таблицы старой таблице.

Кен
источник
2
Это кажется вполне разумным решением. Жаль, что нет инструментов с графическим интерфейсом для автоматизации этой процедуры.
Quolonel Questions
4
хорошее решение, но копируются только типы данных (без первичного ключа и т. д.)
Regisz
1
В качестве альтернативы - просто используйте представление с переупорядоченными столбцами как есть. Ухудшение производительности должно быть минимальным.
PSCL
1
Это лучшее решение.
Николай Шиндаров
23

Один, хотя и неуклюжий вариант переупорядочения столбцов, когда порядок столбцов должен быть абсолютно изменен и используются внешние ключи, - сначала выгрузить всю базу данных с данными, а затем выгрузить только схему ( pg_dump -s databasename > databasename_schema.sql). Затем отредактируйте файл схемы, чтобы изменить порядок столбцов по своему усмотрению, затем воссоздайте базу данных из схемы и, наконец, восстановите данные во вновь созданной базе данных.

Вилле
источник
1
Почему голос против? Как указывает принятый ответ, цитируя PostgreSQL Wiki: «Единственный способ изменить порядок столбцов - либо воссоздать таблицу, либо добавить столбцы и вращать данные, пока не достигнете желаемого макета». Это решение не является оптимальным (ни один из этих ответов не является результатом отсутствия встроенной операции для выполнения задачи), но оно предоставляет способ переупорядочить столбцы в таблице.
Вилле
1
Я повторяю еще раз, хороших способов сделать это нет, и то, что я описал выше, является допустимым способом переупорядочения столбцов, если их абсолютно необходимо переставить. Если вы проголосовали против моего ответа, прокомментируйте, почему вы считаете это неприемлемым решением.
Ville
3
Фактически, это очень хорошее решение, когда таблица является внешним ключом в других таблицах. Все остальные решения в этом сценарии не работают. Наконец, используйте pg_dump
--column-
9

Я не думаю, что в настоящее время это возможно: см. Эту статью в вики Postgresql .

Три обходных пути из этой статьи:

  1. Восстановить таблицу
  2. Добавить столбцы и переместить данные
  3. Скрыть различия с видом.
Майк Вудхаус
источник
5

Откройте таблицу в PGAdmin и на панели SQL внизу скопируйте оператор SQL Create Table. Затем откройте инструмент запросов и вставьте. Если в таблице есть данные, измените имя таблицы на 'new_name', если нет, удалите комментарий «-» в строке Drop Table. При необходимости отредактируйте последовательность столбцов. Обратите внимание на отсутствующую / лишнюю запятую в последнем столбце, если вы ее переместили. Выполните новую команду SQL Create Table. Обновите и ... вуаля.

Для пустых таблиц на этапе проектирования этот способ вполне практичен.

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

INSERT INTO new ( c2, c3, c1 ) SELECT * from old;

... где c2, c3, c1являются колонны c1, c2,c3 из старой таблицы в своих новых позициях. Обратите внимание, что в этом случае вы должны использовать «новое» имя для отредактированной «старой» таблицы, иначе вы потеряете свои данные . В случае, если имена столбцов много, длинные и / или сложные, используйте тот же метод, что и выше, для копирования новой структуры таблицы в текстовый редактор и создания нового списка столбцов там перед копированием в INSERTоператор.

Убедившись, что все в порядке, DROPиспользуйте старую таблицу и измените «новое» имя на «старое», ALTER TABLE new RENAME TO old;и все готово.

Марко Поло
источник
1

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

  1. Получает SQL для создания таблицы из pg_dump
  2. Получает все доступные столбцы из дампа
  3. Ставит столбцы в желаемом порядке
  4. Изменяет исходный pg_dumpзапрос для создания переупорядоченной таблицы с данными
  5. Сбрасывает старый стол
  6. Переименовывает новую таблицу в соответствии со старой таблицей

Его можно использовать, выполнив следующую простую команду:

./reorder.py -n schema -d database table \
    first_col second_col ... penultimate_col ultimate_col --migrate

Он распечатывает sql, чтобы вы могли проверить и протестировать его, и это была большая причина, по которой я его основал pg_dump. Вы можете найти репозиторий на github здесь .

ГаммаИгры
источник
0

Я использую Django, и для него требуется столбец id в каждой таблице, если вы не хотите иметь головную боль. К сожалению, я был неосторожен, и моя таблица bp.geo_location_vague не содержала этого поля. Я подписал маленькую хитрость. Шаг 1:

CREATE VIEW bp.geo_location_vague_vw AS
    SELECT 
        a.id, -- I change order of id column here. 
        a.in_date,
        etc
    FROM bp.geo_location_vague a

Шаг 2: (без создания таблицы - таблица будет создана автоматически!)

SELECT * into bp.geo_location_vague_cp2 FROM bp.geo_location_vague_vw

Шаг 3:

CREATE SEQUENCE bp.tbl_tbl_id_seq;
ALTER TABLE bp.geo_location_vague_cp2 ALTER COLUMN id SET DEFAULT nextval('tbl_tbl_id_seq');
ALTER SEQUENCE bp.tbl_tbl_id_seq OWNED BY bp.geo_location_vague_cp2.id;
SELECT setval('tbl_tbl_id_seq', COALESCE(max(id), 0)) FROM bp.geo_location_vague_cp2;

Потому что мне нужен псевдотип bigserial в таблице. После SELECT * в pg будет создан тип bigint insetad bigserial.

Шаг 4: Теперь мы можем отбросить представление, отбросить исходную таблицу и переименовать новую таблицу со старым именем. Уловка завершилась успешно.

Орлов Конст
источник