Salve a saída PL / pgSQL do PostgreSQL em um arquivo CSV

910

Qual é a maneira mais fácil de salvar a saída PL / pgSQL de um banco de dados PostgreSQL em um arquivo CSV?

Estou usando o PostgreSQL 8.4 com o plugin pgAdmin III e PSQL, de onde executo consultas.

Hoff
fonte
1
Veja também stackoverflow.com/q/1120109/287948
Peter Krauss

Respostas:

1368

Deseja o arquivo resultante no servidor ou no cliente?

Lado do servidor

Se você quiser algo fácil de reutilizar ou automatizar, use o comando COPY incorporado do Postgresql . por exemplo

Copy (Select * From foo) To '/tmp/test.csv' With CSV DELIMITER ',' HEADER;

Essa abordagem é executada inteiramente no servidor remoto - não pode gravar no seu PC local. Ele também precisa ser executado como um "superusuário" do Postgres (normalmente chamado de "root") porque o Postgres não pode impedi-lo de fazer coisas desagradáveis ​​com o sistema de arquivos local dessa máquina.

Na verdade, isso não significa que você precisa estar conectado como superusuário (automatizar isso seria um risco de segurança de um tipo diferente), porque você pode usar a SECURITY DEFINERopçãoCREATE FUNCTION para criar uma função que é executada como se você fosse um superusuário .

A parte crucial é que sua função existe para executar verificações adicionais, não apenas ignorando a segurança - para que você possa escrever uma função que exporte os dados exatos necessários ou para escrever algo que aceite várias opções, desde que conheça uma lista de permissões rigorosa. Você precisa verificar duas coisas:

  1. Quais arquivos o usuário deve ter permissão para ler / gravar no disco? Pode ser um diretório específico, por exemplo, e o nome do arquivo pode ter que ter um prefixo ou extensão adequado.
  2. Quais tabelas o usuário deve poder ler / gravar no banco de dados? Isso normalmente seria definido por GRANTs no banco de dados, mas a função agora está sendo executada como um superusuário, para que as tabelas que normalmente seriam "fora dos limites" fiquem totalmente acessíveis. Você provavelmente não deseja permitir que alguém invoque sua função e adicione linhas no final da sua tabela de "usuários" ...

Eu escrevi um post de blog expandindo essa abordagem , incluindo alguns exemplos de funções que exportam (ou importam) arquivos e tabelas que atendem a condições estritas.


Lado do cliente

A outra abordagem é fazer o tratamento de arquivos no lado do cliente , ou seja, no seu aplicativo ou script. O servidor do Postgres não precisa saber para qual arquivo você está copiando, apenas expõe os dados e o cliente os coloca em algum lugar.

A sintaxe subjacente a isso é o COPY TO STDOUTcomando, e ferramentas gráficas como o pgAdmin o envolverão em uma boa caixa de diálogo.

O psqlcliente da linha de comando possui um "meta-comando" especial chamado \copy, que aceita as mesmas opções do "real" COPY, mas é executado dentro do cliente:

\copy (Select * From foo) To '/tmp/test.csv' With CSV

Observe que não há finalização ;, porque os meta-comandos são finalizados por nova linha, diferente dos comandos SQL.

Dos documentos :

Não confunda COPY com a instrução psql \ copy. \ copy chama COPY FROM STDIN ou COPY TO STDOUT e, em seguida, busca / armazena os dados em um arquivo acessível ao cliente psql. Portanto, a acessibilidade do arquivo e os direitos de acesso dependem do cliente e não do servidor quando \ copy é usado.

A linguagem de programação do aplicativo também pode ter suporte para enviar ou buscar dados, mas geralmente não é possível usar COPY FROM STDIN/ TO STDOUTdentro de uma instrução SQL padrão, porque não há como conectar o fluxo de entrada / saída. O manipulador PostgreSQL do PHP ( não PDO) inclui funções muito básicas pg_copy_frome pg_copy_toque copiam para / de uma matriz PHP, o que pode não ser eficiente para grandes conjuntos de dados.

IMSoP
fonte
131
Obviamente, o exemplo acima exige que, às vezes, o usuário seja um superusuário, aqui está uma versão para pessoas comuns;) echo “COPY (SELECT * from foo) PARA STDOUT COM CSV HEADER” | psql -o '/tmp/test.csv' database_name
Drachenfels
10
@Drachenfels: \copyfunciona também - lá, os caminhos são relativos ao cliente e nenhum ponto e vírgula é necessário / permitido. Veja minha edição.
krlmlr
3
@IMSoP: Como você adicionaria uma instrução COPY a uma função sql (no postgres 9.3)? Portanto, a consulta é salva em um arquivo .csv?
jO.
12
Parece que \copyprecisa ser uma linha. Assim, você não terá a beleza de formatar o sql da maneira que desejar e apenas de colocar uma cópia / função em torno dele.
Isaaclw
1
@AndreSilva Como a resposta indica, \copyé um meta-comando especial no psqlcliente da linha de comando . Não funcionará em outros clientes, como pgAdmin; eles provavelmente terão suas próprias ferramentas, como assistentes gráficos, para realizar este trabalho.
IMSoP
519

Existem várias soluções:

1 psqlcomando

psql -d dbname -t -A -F"," -c "select * from users" > output.csv

Isso tem a grande vantagem de poder usá-lo via SSH, como ssh postgres@host command- permitindo que você obtenha

copyComando 2 postgres

COPY (SELECT * from users) To '/tmp/output.csv' With CSV;

3 psql interativo (ou não)

>psql dbname
psql>\f ','
psql>\a
psql>\o '/tmp/output.csv'
psql>SELECT * from users;
psql>\q

Todos eles podem ser usados ​​em scripts, mas eu prefiro o número 1.

4 pgadmin, mas isso não é programável.

sorin
fonte
32
IMHO, a primeira opção é propensa a erros, porque não inclui escape apropriado de vírgula nos dados exportados.
Piohen
4
Além disso, o psql não cita os valores das células, portanto, se QUALQUER dos seus dados usar o delimitador, seu arquivo será corrompido.
Cerin 08/04
7
@Cerin -t é um sinônimo para --tuples-only (desligar a impressão dos nomes das colunas e rodapés contagem de linhas do resultado, etc) - omiti-lo para obter os cabeçalhos das colunas
ic3b3rg
21
Acabei de testar a reivindicação de escape de vírgula - é verdade que o método nº 1 não escapa vírgulas em valores.
precisa saber é o seguinte
1
também usam "\ rodapé pset" de modo que as contagens de linha não cavar-se no arquivo
techbrownbags
94

No terminal (enquanto conectado ao db), defina a saída para o arquivo cvs

1) Defina o separador de campo como ',':

\f ','

2) Defina o formato de saída desalinhado:

\a

3) Mostrar apenas tuplas:

\t

4) Definir saída:

\o '/tmp/yourOutputFile.csv'

5) Execute sua consulta:

:select * from YOUR_TABLE

6) Saída:

\o

Você poderá encontrar seu arquivo csv neste local:

cd /tmp

Copie-o usando o scpcomando ou edite-o usando o nano:

nano /tmp/yourOutputFile.csv
Marcin Wasiluk
fonte
4
e \ o, a fim de imprimir console novamente
metdos
2
Isso não produzirá um arquivo CSV, apenas gravará a saída do comando no arquivo de texto (o que não o torna separado por vírgula).
Ruslan Kabalin
@RuslanKabalin sim acabo notticed isso e ammended instruções para criar separados por vírgula saída (CVS)
Marcin Wasiluk
5
Eu melhoraria esta resposta observando que a saída "csv" não será escapada adequadamente e cada vez que um comando sql é executado, os resultados são concatenados no arquivo de saída.
Danny Armstrong
E as novas linhas nos valores dos campos? As abordagens COPYou são \copytratadas corretamente (converta para o formato CSV padrão); faz isso?
Curinga
37

Se você estiver interessado em todas as colunas de uma tabela específica, juntamente com os cabeçalhos, poderá usar

COPY table TO '/some_destdir/mycsv.csv' WITH CSV HEADER;

Isso é um pouco mais simples do que

COPY (SELECT * FROM table) TO '/some_destdir/mycsv.csv' WITH CSV HEADER;

que, até onde sei, são equivalentes.

benjwadams
fonte
1
Se a consulta for personalizada (o IE possui aliases de coluna ou ingressa em tabelas diferentes), o cabeçalho imprime os aliases da coluna exatamente como são exibidos na tela.
Devy
34

Unificação de Exportação CSV

Esta informação não está realmente bem representada. Como esta é a segunda vez que eu preciso derivar isso, vou colocar isso aqui para me lembrar, se nada mais.

Realmente, a melhor maneira de fazer isso (tirar o CSV do postgres) é usar o COPY ... TO STDOUTcomando Embora você não queira fazê-lo da maneira mostrada nas respostas aqui. A maneira correta de usar o comando é:

COPY (select id, name from groups) TO STDOUT WITH CSV HEADER

Lembre-se de apenas um comando!

É ótimo para uso em ssh:

$ ssh psqlserver.example.com 'psql -d mydb "COPY (select id, name from groups) TO STDOUT WITH CSV HEADER"' > groups.csv

É ótimo para uso dentro do docker sobre ssh:

$ ssh pgserver.example.com 'docker exec -tu postgres postgres psql -d mydb -c "COPY groups TO STDOUT WITH CSV HEADER"' > groups.csv

É ótimo na máquina local:

$ psql -d mydb -c 'COPY groups TO STDOUT WITH CSV HEADER' > groups.csv

Ou dentro da janela de encaixe na máquina local ?:

docker exec -tu postgres postgres psql -d mydb -c 'COPY groups TO STDOUT WITH CSV HEADER' > groups.csv

Ou em um cluster kubernetes, na janela de encaixe, sobre HTTPS ??:

kubectl exec -t postgres-2592991581-ws2td 'psql -d mydb -c "COPY groups TO STDOUT WITH CSV HEADER"' > groups.csv

Tão versátil, muitas vírgulas!

Você até?

Sim, fiz, aqui estão minhas anotações:

As CÓPIAS

Usar /copyefetivamente executa operações de arquivo em qualquer sistema em que o psqlcomando esteja sendo executado, como o usuário que o está executando 1 . Se você se conectar a um servidor remoto, é simples copiar arquivos de dados no sistema executando psqlpara / do servidor remoto.

COPYexecuta operações de arquivo no servidor como a conta de usuário do processo de back-end (padrão postgres), os caminhos e as permissões de arquivo são verificados e aplicados de acordo. Se estiver usando TO STDOUT, as verificações de permissões de arquivo serão ignoradas.

Ambas as opções requerem movimentação de arquivo subsequente se psqlnão estiver em execução no sistema em que você deseja que o CSV resultante resida. Este é o caso mais provável, na minha experiência, quando você trabalha principalmente com servidores remotos.

É mais complexo configurar algo como um túnel TCP / IP sobre ssh em um sistema remoto para saída CSV simples, mas para outros formatos de saída (binários) pode ser melhor passar /copypor uma conexão em túnel, executando um local psql. Da mesma forma, para grandes importações, mover o arquivo de origem para o servidor e usá-lo COPYé provavelmente a opção de maior desempenho.

Parâmetros PSQL

Com os parâmetros psql, você pode formatar a saída como CSV, mas há desvantagens como lembrar de desativar o pager e não obter cabeçalhos:

$ psql -P pager=off -d mydb -t -A -F',' -c 'select * from groups;'
2,Technician,Test 2,,,t,,0,,                                                                                                                                                                   
3,Truck,1,2017-10-02,,t,,0,,                                                                                                                                                                   
4,Truck,2,2017-10-02,,t,,0,,

Outras ferramentas

Não, eu só quero tirar o CSV do meu servidor sem compilar e / ou instalar uma ferramenta.

joshperry
fonte
1
Onde os resultados são salvos? Minha consulta é executada, mas o arquivo não aparece em nenhum lugar do meu computador. Isto é o que estou fazendo: COPY (selecione a, b de c onde d = '1') PARA STDOUT COM CSVHEADER> abcd.csv
kRazzy R
1
@kRazzyR A saída vai para stdout do comando psql, então, em última análise, o que você faz com stdout é para onde os dados vão. Nos meus exemplos, uso '> file.csv' para redirecionar para um arquivo. Você quer ter certeza de que está fora do comando que está sendo enviado para o servidor através do parâmetro psql -c. Veja o exemplo da 'máquina local'.
Joshperry
1
Obrigado pela explicação completa. O comando copy é irremediavelmente complexo com o psql. Eu geralmente acabo usando um cliente de banco de dados gratuito (dbeaver community edition) para importar e exportar arquivos de dados. Ele fornece boas ferramentas de mapeamento e formatação. Sua resposta fornece ótimos exemplos detalhados para copiar de sistemas remotos.
Rich Lysakowski PhD 28/11/19
24

Eu tive que usar o \ COPY porque recebi a mensagem de erro:

ERROR:  could not open file "/filepath/places.csv" for writing: Permission denied

Então eu usei:

\Copy (Select address, zip  From manjadata) To '/filepath/places.csv' With CSV;

e está funcionando

maudulus
fonte
17

psql pode fazer isso por você:

edd@ron:~$ psql -d beancounter -t -A -F"," \
                -c "select date, symbol, day_close " \
                   "from stockprices where symbol like 'I%' " \
                   "and date >= '2009-10-02'"
2009-10-02,IBM,119.02
2009-10-02,IEF,92.77
2009-10-02,IEV,37.05
2009-10-02,IJH,66.18
2009-10-02,IJR,50.33
2009-10-02,ILF,42.24
2009-10-02,INTC,18.97
2009-10-02,IP,21.39
edd@ron:~$

Consulte man psqlpara obter ajuda sobre as opções usadas aqui.

Dirk Eddelbuettel
fonte
12
Este não é um arquivo CSV verdadeiro - observe se ele queimar se houver vírgulas nos dados -, portanto, é preferível usar o suporte incorporado ao COPY. Mas essa técnica geral é útil como um hack rápido para exportar do Postgres para outros formatos delimitados além do CSV.
9789 Greg Smith #
17

Nova versão - psql 12 - será suportada --csv.

psql - devel

--csv

Muda para o modo de saída CSV (valores separados por vírgula). Isso é equivalente ao formato \ pset csv .


csv_fieldsep

Especifica o separador de campos a ser usado no formato de saída CSV. Se o caractere separador aparecer no valor de um campo, esse campo será gerado entre aspas duplas, seguindo as regras CSV padrão. O padrão é uma vírgula.

Uso:

psql -c "SELECT * FROM pg_catalog.pg_tables" --csv  postgres

psql -c "SELECT * FROM pg_catalog.pg_tables" --csv -P csv_fieldsep='^'  postgres

psql -c "SELECT * FROM pg_catalog.pg_tables" --csv  postgres > output.csv
Lukasz Szozda
fonte
16

Estou trabalhando no AWS Redshift, que não suporta o COPY TOrecurso.

Porém, minha ferramenta de BI suporta CSVs delimitados por tabulação, então usei o seguinte:

 psql -h dblocation -p port -U user -d dbname -F $'\t' --no-align -c "SELECT * FROM TABLE" > outfile.csv
calcsam
fonte
11

No pgAdmin III, há uma opção para exportar para o arquivo da janela de consulta. No menu principal, é Consulta -> Executar para arquivar ou existe um botão que faz a mesma coisa (é um triângulo verde com um disquete azul em oposição ao triângulo verde liso que apenas executa a consulta). Se você não estiver executando a consulta na janela de consulta, eu faria o que o IMSoP sugeriu e usaria o comando copy.

Amanda Nyren
fonte
A resposta do IMSoP não funcionou para mim, pois eu precisava ser um superadministrador. Isso funcionou um prazer. Obrigado!
Mike
9

Tentei várias coisas, mas poucas delas conseguiram me fornecer o CSV desejado com detalhes do cabeçalho.

Aqui está o que funcionou para mim.

psql -d dbame -U username \
  -c "COPY ( SELECT * FROM TABLE ) TO STDOUT WITH CSV HEADER " > \
  OUTPUT_CSV_FILE.csv
pyAddict
fonte
9

Eu escrevi uma pequena ferramenta chamada psql2csvque encapsula o COPY query TO STDOUTpadrão, resultando em um CSV adequado. Sua interface é semelhante a psql.

psql2csv [OPTIONS] < QUERY
psql2csv [OPTIONS] QUERY

A consulta é assumida como sendo o conteúdo de STDIN, se presente, ou o último argumento. Todos os outros argumentos são encaminhados para o psql, exceto estes:

-h, --help           show help, then exit
--encoding=ENCODING  use a different encoding than UTF8 (Excel likes LATIN1)
--no-header          do not output a header
fphilipe
fonte
2
Funciona bem. Obrigado.
AlexM
6

Se você tiver uma consulta mais longa e quiser usar o psql, coloque sua consulta em um arquivo e use o seguinte comando:

psql -d my_db_name -t -A -F";" -f input-file.sql -o output-file.csv
Andres Kull
fonte
FWIW, eu tive que usar -F","em vez de -F";"gerar um arquivo CSV que abriria corretamente no MS Excel
CFL_Jeff
4

Para fazer o download do arquivo CSV com nomes de colunas como HEADER, use este comando:

Copy (Select * From tableName) To '/tmp/fileName.csv' With CSV HEADER;
murli
fonte
1

Eu recomendo o DataGrip , um IDE de banco de dados da JetBrains. Você pode exportar uma consulta SQL para um arquivo CSV e configurar o encapsulamento ssh com facilidade. Quando a documentação se refere ao "conjunto de resultados", eles significam o resultado retornado por uma consulta SQL no console.

Não estou associado ao DataGrip, adoro o produto!

skeller88
fonte
Suponho que o voto negativo foi devido à falta de contexto / explicação, por isso vinculei à documentação do DataGrip. Se houver um motivo diferente para o voto negativo, entre em contato. Eu usei as soluções CLI acima e o DataGrip é muito mais fácil para consultas menores.
precisa saber é o seguinte
O problema com o DataGrip é que ele controla sua carteira. Não é grátis. Experimente a edição da comunidade do DBeaver em dbeaver.io . É uma ferramenta de banco de dados multi-plataforma FOSS para programadores, DBAs e analistas de SQL que suporta todos os bancos de dados populares: MySQL, PostgreSQL, SQLite, Oracle, DB2, SQL Server, Sybase, MS Access, Teradata, Firebird, Hive, Presto, etc.
Rich Lysakowski PhD 28/11/19
Legal, eu vou dar uma olhada. Que tal você também repassar seu comentário como resposta?
skeller88
0

O JackDB , um cliente de banco de dados no seu navegador da Web, torna isso muito fácil. Especialmente se você estiver no Heroku.

Permite conectar-se a bancos de dados remotos e executar consultas SQL neles.

                                                                                                                                                       Fonte (fonte: jackdb.com )jackdb-heroku


Depois que seu banco de dados estiver conectado, você poderá executar uma consulta e exportar para CSV ou TXT (veja o canto inferior direito).


jackdb-export

Nota: Eu não sou de forma alguma afiliado ao JackDB. Atualmente, uso seus serviços gratuitos e acho que é um ótimo produto.

Dennis
fonte
0

Por solicitação do @ skeller88, estou reposicionando meu comentário como resposta, para que não se perca por pessoas que não leem todas as respostas ...

O problema com o DataGrip é que ele controla sua carteira. Não é grátis. Experimente a edição da comunidade do DBeaver em dbeaver.io. É uma ferramenta de banco de dados multi-plataforma FOSS para programadores, DBAs e analistas de SQL que suporta todos os bancos de dados populares: MySQL, PostgreSQL, SQLite, Oracle, DB2, SQL Server, Sybase, MS Access, Teradata, Firebird, Hive, Presto, etc.

O DBeaver Community Edition facilita a conexão com um banco de dados, emite consultas para recuperar dados e, em seguida, faça o download do conjunto de resultados para salvá-lo em CSV, JSON, SQL ou outros formatos de dados comuns. É um concorrente viável do FOSS para o TOAD para Postgres, o TOAD para SQL Server ou o Toad para Oracle.

Não tenho afiliação com o DBeaver. Adoro o preço e a funcionalidade, mas desejo que eles abram mais o aplicativo DBeaver / Eclipse e facilitem a adição de widgets de análise ao DBeaver / Eclipse, em vez de exigir que os usuários paguem pela assinatura anual para criar gráficos e tabelas diretamente dentro a aplicação. Minhas habilidades de codificação em Java estão enferrujadas e não estou precisando de semanas para reaprender a criar widgets do Eclipse, apenas para descobrir que o DBeaver desativou a capacidade de adicionar widgets de terceiros ao DBeaver Community Edition.

Os usuários do DBeaver têm informações sobre as etapas para criar widgets de análise para adicionar ao Community Edition do DBeaver?

Rich Lysakowski PhD
fonte
-3
import json
cursor = conn.cursor()
qry = """ SELECT details FROM test_csvfile """ 
cursor.execute(qry)
rows = cursor.fetchall()

value = json.dumps(rows)

with open("/home/asha/Desktop/Income_output.json","w+") as f:
    f.write(value)
print 'Saved to File Successfully'
user9279273
fonte
3
Por favor expolain que você fez a edição de resposta, código de evitar única resposta
GGO
3
Obrigado por este trecho de código, que pode fornecer ajuda limitada a curto prazo. Uma explicação adequada melhoraria bastante seu valor a longo prazo, mostrando por que essa é uma boa solução para o problema e a tornaria mais útil para futuros leitores com outras perguntas semelhantes. Por favor edite sua resposta para adicionar alguma explicação, incluindo as suposições que você fez.
Toby Speight 27/02
2
Isso produzirá um arquivo json, não um arquivo csv.
Nvigt