Ao criar uma ferramenta de gerenciamento de colunas, me deparei com a necessidade de replicar tabelas rapidamente no PostgreSQL para não testar novas ferramentas com tabelas que não são de teste. Para testar efetivamente a nova ferramenta de coluna que pretendo usar na tabela parts
, criei essa nova ferramenta para duplicar parts
, para terminar com uma parts1
tabela. Quando pensei que finalmente tinha resolvido todos os problemas, encontrei o seguinte erro quando a ferramenta de coluna exclui a tabela:
ERRO: não é possível descartar partes da tabela porque outros objetos dependem dela DETALHE: padrão para o ID da coluna parts1 da tabela depende da sequência parts_id_seq1
Passei a maior parte do meu dia trabalhando nessa solução, então, resumindo, posso simplesmente usar funções de string para renomear a SEQUENCE_NAME
variável para desassociar a parts
tabela da parts
tabela ou é um problema mais complicado do que isso? Aqui está a consulta:
DO $$
DECLARE
SEQUENCE_NAME VARCHAR;
BEGIN
SELECT s.relname INTO SEQUENCE_NAME
FROM pg_class AS s JOIN pg_depend d ON d.objid = s.oid
INNER JOIN pg_class AS t ON d.objid = s.oid AND d.refobjid = t.oid
INNER JOIN pg_attribute AS a ON (d.refobjid, d.refobjsubid) = (a.attrelid, a.attnum)
INNER JOIN pg_namespace AS n ON n.oid = s.relnamespace
WHERE s.relkind = 'S'
AND n.nspname = 'public'
AND t.relname='parts';
LOCK TABLE parts;
CREATE TABLE parts1 (LIKE parts INCLUDING ALL);
INSERT INTO parts1 SELECT * FROM parts;
PERFORM setval(SEQUENCE_NAME::regclass, (SELECT max(id) FROM parts)+1);
END;
$$ LANGUAGE plpgsql;
Para criar uma cópia o mais próxima possível, use
INCLUDING ALL
withCREATE TABLE .. (LIKE ..)
, pois pode haver qualquer número de colunas com padrões que você obviamente deseja copiar.Você só quer
serial
que as colunas tenham sua própria sequência independente, o que faz muito sentido e provavelmente deveria ter sido o comportamento padrão para começar.O Postgres 10 "consertou" isso adicionando
IDENTITY
colunas em conformidade com o padrão SQL, que possuem sequências internas exclusivamente dedicadas e se comportam conforme desejado com arquivosCREATE TABLE .. (LIKE ..)
. O manual:Ênfase em negrito minha. As colunas seriais existentes permanecem inalteradas. Considere a substituição
serial
de colunas. Ver:Função para copiar tabelas com (ou sem)
serial
colunasEmbora as
serial
colunas ainda estejam envolvidas, esta função deve fazer o trabalho:Copia qualquer tabela fornecida (deve existir) com um novo nome fornecido e colunas independentes
serial
(se houver).Os dados não estão incluídos, é trivial copiá-los também.
Ligar:
Ou:
Produz e executa o código SQL do formulário:
A fonte ( 1º parâmetro) deve ser uma tabela, visualização, visualização materializada, tipo composto ou tabela externa. Opcionalmente qualificado pelo esquema.
O segundo parâmetro é o novo nome da tabela.
O terceiro parâmetro é o esquema da nova tabela. Se não for fornecido, o padrão é o esquema da fonte.
A coluna do sistema
pg_attrdef.adsrc
foi descartada no Postgres 12. Usarpg_get_expr(ad.adbin, ad.adrelid)
em vez disso conforme instruído no manual Funciona em versões anteriores também.Somente
serial
as colunas obtêm sua própria sequência. Outros padrões de coluna são copiados inalterados - inclusivenextval()
de uma sequência que não pertence à coluna ou difere de alguma forma de um arquivoserial
.A função é segura contra injeção de SQL e deve funcionar com tabelas arbitrárias e nomes de colunas.
db<>fiddle aqui
Old sqlfiddle
O problema é que sua tabela peças1 usa a sequência da tabela de peças (ao invés de sua própria sequência)... assim ele reclama que você não pode descartar a tabela de peças porque a tabela de peças1 depende dela (via valor padrão para um dos as colunas)... Você está obtendo esse comportamento em como está criando a tabela parts1...
CRIAR TABELA - veja a
LIKE source_table [ like_option ... ]
seçãoVocê pode obter os resultados desejados criando a tabela como você fez e, em seguida, criando novas sequências, definindo novos valores padrão e criando novas dependências para cada coluna SERIAL (já que o comportamento da opção LIKE aparentemente não cria suas próprias sequências a partir de desta vez).
As etapas para realizar o acima são fornecidas na resposta de Deszo aqui
(copiei por comodidade.. alterei o passo 2 dele já terá uma tabela criada)
Você também pode usar este SQL para ajudar a identificar quais colunas pertencem à pkey para a tabela em questão, embora isso não ajude a identificar TODAS as colunas seriais (se uma não for uma pkey).
Consulte a resposta de Erwin Brandstetter para (suponho) uma solução mais completa.
Eu queria liberar pelo menos a função PHP direta (eventualmente lançarei as ferramentas que estou construindo para algo como o Github), embora ainda não tenha tempo para fazer muito mais do que postar aqui, pelo menos. Espero que isso economize o tempo dos outros e sinta-se à vontade para sugerir melhorias. Não tenho certeza de quão seguro é o código (é apenas uma ferramenta que estou usando apenas para desenvolvimento e atualmente para um cliente que estou configurando um site somente para intranet), embora tenha feito o possível para seguir o conselho do outras perguntas/respostas de Erwin Brandstetter e Joishi Bodio.
Exemplo de solicitação de URL:
Eu simplesmente tenho funções de chamada PHP e, como frequentemente repito as ações que minhas ferramentas PostgreSQL executam, simplesmente armazeno as informações em uma
$_GET
matriz.