it-roy-ru.com

Сохранить вывод PL / pgSQL из PostgreSQL в файл CSV

Какой самый простой способ сохранить вывод PL/pgSQL из базы данных PostgreSQL в файл CSV?

Я использую PostgreSQL 8.4 с плагином pgAdmin III и PSQL, откуда я запускаю запросы.

795
Hoff

Хотите ли вы получить полученный файл на сервере или на клиенте?

Серверная сторона

Если вы хотите что-то простое для повторного использования или автоматизации, вы можете использовать встроенную в Postgresql команду COPY . например.

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

Этот подход полностью работает на удаленном сервере - он не может записывать на ваш локальный ПК. Его также нужно запускать как "суперпользователь" Postgres (обычно называемый "root"), потому что Postgres не может остановить его, делая неприятные вещи с локальной файловой системой этого компьютера.

Это на самом деле не означает, что вы должны быть подключены как суперпользователь (автоматизация, которая будет представлять угрозу безопасности другого типа), потому что вы можете использовать параметр SECURITY DEFINER для CREATE FUNCTION , чтобы сделать функцию, которая работает так, как если бы вы были суперпользователем .

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

  1. Какие файлы должны быть разрешены пользователю для чтения/записи на диск? Например, это может быть определенный каталог, а имя файла может иметь подходящий префикс или расширение.
  2. Какие таблицы должен иметь пользователь для чтения/записи в базе данных? Обычно это определяется GRANTs в базе данных, но функция теперь работает как суперпользователь, поэтому таблицы, которые обычно бывают "вне границ", будут полностью доступны. Вы, вероятно, не хотите, чтобы кто-то вызывал вашу функцию и добавлял строки в конец вашей таблицы "users" ...

Я написал сообщение в блоге, расширяющее этот подход , включая некоторые примеры функций, которые экспортируют (или импортируют) файлы и таблицы, соответствующие строгим условиям.


Сторона клиента

Другой подход состоит в том, чтобы выполнять обработку файлов на стороне клиента , т.е. в вашем приложении или скрипте. Серверу Postgres не нужно знать, в какой файл вы копируете, он просто выплевывает данные, а клиент помещает их куда-то.

Основной синтаксис для этого - команда COPY TO STDOUT, и графические инструменты, такие как pgAdmin, обернут ее для вас в диалоге Nice.

Клиент командной строки psql имеет специальную мета-команду, называемую \copy, который принимает все те же параметры, что и "реальное" COPY, но запускается внутри клиента:

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

Обратите внимание, что нет завершающего ;, потому что метакоманды заканчиваются символом новой строки, в отличие от команд SQL.

От документы :

Не путайте COPY с инструкцией psql\copy.\copy вызывает COPY FROM STDIN или COPY TO STDOUT, а затем извлекает/сохраняет данные в файле, доступном для клиента psql. Таким образом, доступность файла и права доступа зависят от клиента, а не от сервера при использовании\copy.

Ваш язык прикладного программирования может также иметь поддержку для извлечения или извлечения данных, но вы обычно не можете использовать COPY FROM STDIN/TO STDOUT в стандартном операторе SQL, потому что нет способа соединить ввод/выходной поток. PHP-обработчик PostgreSQL ( not PDO) включает в себя очень простые pg_copy_from и pg_copy_to функции, которые копируют в/из PHP массив, который может быть неэффективен для больших наборов данных.

1202
IMSoP

Есть несколько решений:

1 psql команда

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

Это имеет большое преимущество, заключающееся в том, что вы можете использовать его через SSH, например, ssh [email protected] command - позволяя вам получить

2 команды postgres copy

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

3 psql интерактивный (или нет)

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

Все они могут быть использованы в сценариях, но я предпочитаю # 1.

4 пгадмина но это не в сценарии.

462
sorin

В терминале (при подключении к БД) установите вывод в файл cvs

1) Установите разделитель полей на ',':

\f ','

2) Установите формат вывода без выравнивания:

\a

3) Показывать только кортежи:

\t

4) Установите выход:

\o '/tmp/yourOutputFile.csv'

5) Выполните ваш запрос:

:select * from YOUR_TABLE

6) Результат:

\o

После этого вы сможете найти свой CSV-файл в этом месте:

cd /tmp

Скопируйте его с помощью команды scp или отредактируйте с помощью nano:

nano /tmp/yourOutputFile.csv
85
Marcin Wasiluk

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

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

Это немного проще, чем

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

которые, насколько мне известно, эквивалентны.

34
benjwadams

CSV Экспорт унификации

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

Действительно лучший способ сделать это (получить CSV из postgres) - это использовать команду COPY ... TO STDOUT. Хотя вы не хотите делать это так, как показано в ответах здесь. Правильный способ использования команды:

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

Запомните только одну команду!

Отлично подходит для использования поверх ssh:

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

Он отлично подходит для использования в докере по ssh:

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

Это даже здорово на локальной машине:

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

Или внутри докера на локальной машине?

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

Или в кластере kubernetes, в докере, через HTTPS ??

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

Так универсально, много запятых!

Ты когда-нибудь?

Да, вот мои заметки:

КОПЫ

Использование /copy эффективно выполняет файловые операции в любой системе, в которой работает команда psql, как пользователь, выполняющий ее 1 . Если вы подключаетесь к удаленному серверу, просто скопировать файлы данных в системе, выполняющей psql, на/с удаленного сервера.

COPY выполняет файловые операции на сервере в качестве учетной записи пользователя внутреннего процесса (по умолчанию postgres), пути к файлам и разрешения проверяются и применяются соответственно. При использовании TO STDOUT проверки прав доступа к файлам обходятся.

Обе эти опции требуют последующего перемещения файла, если psql не выполняется в системе, где вы хотите, чтобы результирующий CSV в конечном итоге находился. По моему опыту, это наиболее вероятный случай, когда вы в основном работаете с удаленными серверами.

Более сложно настроить что-то вроде туннеля TCP/IP через ssh на удаленную систему для простого вывода CSV, но для других форматов вывода (двоичного) может быть лучше использовать /copy через туннельное соединение, выполняя локальное psql. Аналогичным образом, при большом импорте перемещение исходного файла на сервер и использование COPY, вероятно, является наиболее эффективным вариантом.

Параметры PSQL

С параметрами psql вы можете отформатировать вывод как CSV, но есть и недостатки, такие как необходимость помнить, чтобы отключить пейджер и не получать заголовки:

$ 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,,

Другие инструменты

Нет, я просто хочу вывести CSV из моего сервера без компиляции и/или установки инструмента.

23
joshperry

Мне пришлось использовать\COPY, потому что я получил сообщение об ошибке:

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

Поэтому я использовал:

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

и это функционирует

22
maudulus

psql может сделать это для вас:

[email protected]:~$ 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
[email protected]:~$

Смотрите man psql для справки об опциях, используемых здесь.

16
Dirk Eddelbuettel

Я работаю над AWS Redshift, который не поддерживает функцию COPY TO.

Мой инструмент BI поддерживает CSV с разделителями табуляции, поэтому я использовал следующее:

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

В pgAdmin III есть возможность экспортировать в файл из окна запроса. В главном меню это Query -> Execute to file или есть кнопка, которая делает то же самое (это зеленый треугольник с синим гибким диском в отличие от простого зеленого треугольника, который просто выполняет запрос). Если вы не запускаете запрос из окна запроса, я бы сделал то, что предложил IMSoP, и использовал бы команду копирования.

11
Amanda Nyren

Новая версия - PSQL 12 - будет поддерживать --csv.

psql - devel

- CSV

Переключение в режим вывода CSV (значения, разделенные запятыми). Это эквивалентно \pset формату csv .


csv_fieldsep

Определяет разделитель полей, который будет использоваться в выходном формате CSV. Если символ-разделитель появляется в значении поля, это поле выводится в двойных кавычках, следуя стандартным правилам CSV. По умолчанию используется запятая.

Использование:

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
9
Lukasz Szozda

Я написал небольшой инструмент под названием psql2csv , который инкапсулирует шаблон COPY query TO STDOUT, что приводит к правильному CSV. Его интерфейс похож на psql.

psql2csv [OPTIONS] < QUERY
psql2csv [OPTIONS] QUERY

Предполагается, что запрос представляет собой содержимое STDIN, если оно есть, или последний аргумент. Все остальные аргументы перенаправляются в psql, кроме следующих:

-h, --help           show help, then exit
--encoding=ENCODING  use a different encoding than UTF8 (Excel likes LATIN1)
--no-header          do not output a header
7
fphilipe

Я попробовал несколько вещей, но немногие из них смогли дать мне желаемый CSV с подробностями заголовка.

Вот что сработало для меня.

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

Если у вас более длинный запрос и вы хотите использовать psql, поместите запрос в файл и используйте следующую команду:

psql -d my_db_name -t -A -F";" -f input-file.sql -o output-file.csv
5
Andres Kull

Чтобы загрузить CSV-файл с именами столбцов в качестве HEADER, используйте следующую команду:

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

JackDB , клиент базы данных в вашем веб-браузере, делает это действительно легко. Особенно, если ты на Heroku.

Это позволяет вам подключаться к удаленным базам данных и выполнять SQL-запросы к ним.

Источник jackdb-heroku http://static.jackdb.com/assets/img/blog/jackdb-heroku-oauth-connect.gif


Как только ваша БД подключена, вы можете выполнить запрос и экспортировать в CSV или TXT (см. Справа внизу).


jackdb-export

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

1
Dennis