Como altero a posição de uma coluna em uma tabela de banco de dados PostgreSQL?


Respostas:


107

" Alterar a posição da coluna " no PostgreSQL Wiki diz:

O PostgreSQL atualmente define a ordem das colunas com base na attnumcoluna da pg_attributetabela. A única maneira de alterar a ordem das colunas é recriar a tabela ou adicionar colunas e girar os dados até atingir o layout desejado.

Isso é muito fraco, mas em sua defesa, no SQL padrão, também não há solução para reposicionar uma coluna. As marcas de banco de dados que oferecem suporte à alteração da posição ordinal de uma coluna estão definindo uma extensão para a sintaxe SQL.

Outra ideia me ocorre: você pode definir um VIEWque especifica a ordem das colunas como você gosta, sem alterar a posição física da coluna na tabela base.


3
@Dana: Acho que é isso o que significa "recriar a mesa" no artigo wiki.
— Bill Karwin

2
'despejar o banco de dados': ótima maneira de danificar dados. e, portanto, o efeito "limpar o banco de dados massivo".
— Kent Fredric

31
@Kent: Duvidoso, os desenvolvedores do postgres percorrem um longo caminho para garantir a consistência dos dados e isso certamente se aplicaria ao pg_dump. Afinal, de que adianta fazer backups db se a restauração for interrompida?
— Dana the Sane

@Dana, sim, mas você está adicionando 1) um grande processo para despejar, e então você descarta, e então você tem uma carga que consome muito tempo. Se você tiver um banco de dados muito grande, o que geralmente é o caso com 37 colunas, terá riscos de bloqueio de E / S de disco.
— Kent Fredric

@DanatheSane estes são super antigos comentários, mas o que Bill estava dizendo é essencialmente a mesma coisa, em vez de fazer um despejo de banco de dados completo, você simplesmente despejar a mesa (e dependências), matar o original, em seguida, recriar. Não há necessidade de colocar todo o banco de dados offline ou perder tempo recriando algo que não seja afetado. Por outro lado, se houver muitas dependências, descobri que fazer um dump completo (como você sugeriu) é muito mais fácil.
— vol7ron

37

No PostgreSQL, ao adicionar um campo, ele seria adicionado no final da tabela. Se precisarmos inserir em uma posição particular, então

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;

4
Uau, isso é ótimo, tenho certeza que essa deve ser a resposta aceita!
— Tommaso Thea Cioni

Sim, é muito útil, muito obrigado!
— Acuna

Você também pode copiar a tabela atual para uma nova tabela antiga como este: CREATE TABLE tabela antiga AS SELECT * FROM nome da tabela;
— Ryan

29

Este post é antigo e provavelmente está resolvido, mas eu tive o mesmo problema. Resolvi isso criando uma visão da tabela original especificando a nova ordem das colunas.

A partir daqui, eu poderia usar a visualização ou criar uma nova tabela a partir da visualização.

    CRIAR VISUALIZAR original_tab_vw AS
    SELECIONE a.col1, a.col3, a.col4, a.col2
    FROM original_tab a
    ONDE a.col1 NÃO É NULO - ou qualquer outra coisa
    SELECT * INTO new_table FROM original_tab_vw

Renomeie ou elimine a tabela original e defina o nome da nova tabela para a tabela antiga.


2
Esta parece ser uma solução bastante razoável. É uma pena que não existam ferramentas GUI para automatizar este procedimento.
— Quolonel Perguntas

4
boa solução, mas apenas os tipos de dados são copiados (sem chave primária, etc.)
— Regisz

1
Alternativamente - apenas use a visualização com as colunas reordenadas como estão. Deve haver degradação de desempenho mínima.
— pscl

1
essa é a melhor solução.
— Nikolay Shindarov

23

Uma, embora seja uma opção desajeitada para reorganizar as colunas quando a ordem das colunas deve ser absolutamente alterada e as chaves estrangeiras estão em uso, é primeiro despejar todo o banco de dados com dados e, em seguida, despejar apenas o esquema ( pg_dump -s databasename > databasename_schema.sql). Em seguida, edite o arquivo de esquema para reorganizar as colunas como desejar, recrie o banco de dados do esquema e, finalmente, restaure os dados no banco de dados recém-criado.


1
Por que um downvote? Como a resposta aceita indica, citando o PostgreSQL Wiki: »A única maneira de alterar a ordem das colunas é recriar a tabela ou adicionar colunas e girar os dados até chegar ao layout desejado.» Essa solução não é a ideal (nenhuma dessas respostas está na ausência de uma operação integrada para realizar a tarefa), mas fornece uma maneira de reorganizar as colunas em uma tabela.
— Ville

1
Digo novamente, não há boas maneiras de fazer isso, e o que delineei acima é uma maneira válida de reorganizar as colunas, se for absolutamente necessário reorganizá-las. Se você votar contra minha resposta, comente por que você acha que é uma solução inaceitável.
— Ville

3
Na verdade, esta é uma solução muito boa quando a tabela é uma chave estrangeira em outras tabelas. Todas as outras soluções não funcionam neste cenário. Por último, use pg_dump --column-inserts -s databasename> databasename_schema.sql
— Alejandro Salamanca Mazuelo


5

Abra a tabela no PGAdmin e no painel SQL na parte inferior copie a instrução SQL Create Table. Em seguida, abra a ferramenta de consulta e cole. Se a tabela tiver dados, altere o nome da tabela para 'novo_nome', caso contrário, exclua o comentário "-" na linha Eliminar Tabela. Edite a sequência da coluna conforme necessário. Cuidado com a vírgula ausente / supérflua na última coluna, caso você a tenha movido. Execute o novo comando SQL Create Table. Atualize e ... voilà.

Para tabelas vazias na fase de design, este método é bastante prático.

Caso a tabela contenha dados, precisamos reorganizar a sequência das colunas dos dados também. Isso é fácil: use INSERTpara importar a tabela antiga para sua nova versão com:

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

... onde c2, c3, c1são as colunas c1, c2, c3da antiga mesa em suas novas posições. Observe que, neste caso, você deve usar um nome 'novo' para a tabela 'antiga' editada ou perderá seus dados . No caso dos nomes das colunas serem muitos, longos e / ou complexos, use o mesmo método acima para copiar a nova estrutura da tabela em um editor de texto e crie a nova lista de colunas antes de copiá-la para a INSERTinstrução.

Depois de verificar se está tudo bem, DROPvá para a tabela antiga e mude o nome 'novo' para 'antigo' usando ALTER TABLE new RENAME TO old;e pronto.


1

Eu estava trabalhando para reordenar várias tabelas e não queria ter que escrever as mesmas consultas repetidamente, então fiz um script para fazer tudo para mim. Essencialmente, ele:

  1. Obtém o SQL de criação de tabela de pg_dump
  2. Obtém todas as colunas disponíveis do despejo
  3. Coloca as colunas na ordem desejada
  4. Modifica a pg_dumpconsulta original para criar uma tabela reordenada com dados
  5. Cai a mesa velha
  6. Renomeia a nova tabela para corresponder à tabela antiga

Ele pode ser usado executando o seguinte comando simples:

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

Ele imprime o sql para que você possa verificá-lo e testá-lo, esse foi um grande motivo pelo qual eu o baseei pg_dump. Você pode encontrar o repositório github aqui .


0

Eu uso Django e requer coluna id em cada tabela se você não quiser ter dor de cabeça. Infelizmente, fui descuidado e minha tabela bp.geo_location_vague não continha este campo. Eu iniciei um pequeno truque. Passo 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

Etapa 2: (sem criar tabela - a tabela será criada automaticamente!)

SELECT * into bp.geo_location_vague_cp2 FROM bp.geo_location_vague_vw

Etapa 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;

Porque preciso ter um grande pseudótipo serial na tabela. Depois de SELECT * na pg, será criado o tipo bigint insetad bigserial.

passo 4: agora podemos eliminar a visão, eliminar a tabela de origem e renomear a nova tabela com o nome antigo. O truque foi encerrado com sucesso.


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.