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

694

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

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

Теги:
csv
postgresql-copy

16 ответов

1048
Лучший ответ

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

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

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

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

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

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

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

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

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


Клиентская сторона

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

Подходящим синтаксисом для этого является команда COPY TO STDOUT, а графические инструменты, такие как pgAdmin, завершают ее для вас в приятном диалоговом окне.

Клиент командной строки 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 (не PDO) включает в себя очень простой pg_copy_from и pg_copy_to, которые копируются в/из массива PHP, что может быть неэффективным для больших наборов данных.

  • 112
    Очевидно, что в приведенном выше примере иногда требуется, чтобы пользователь был суперпользователем, вот версия для обычных людей;) echo «COPY (SELECT * from foo) TO STOOUT с CSV HEADER» | psql -o '/tmp/test.csv' имя_базы_данных
  • 10
    @Drachenfels: \copy тоже работает - там, пути относительно клиента, и точка с запятой не нужна / не разрешена. Смотрите мое редактирование.
Показать ещё 10 комментариев
411

Существует несколько решений:

1 psql команда

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

Это имеет большое преимущество, что вы можете использовать его через SSH, например ssh postgres@host 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 pgadmin, но это невозможно для сценариев.

  • 29
    ИМХО первый вариант подвержен ошибкам, потому что он не включает в себя правильное экранирование запятой в экспортируемых данных.
  • 0
    Насколько я помню, @Piohen цитирует строки, но я не уверен на 100%, лучше проверить.
Показать ещё 11 комментариев
79

В терминале (при подключении к db) установите вывод в файл 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
  • 4
    и \ о, чтобы снова распечатать консоль
  • 1
    Это не создаст файл CSV, он просто запишет вывод команды в текстовый файл (который не делает его разделенным запятыми).
Показать ещё 4 комментария
31

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

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

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

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

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

  • 1
    Если запрос является пользовательским (IE имеет псевдонимы столбцов или объединяет разные таблицы), заголовок будет печатать псевдонимы столбцов так же, как он отображается на экране.
20

Мне пришлось использовать \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;

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

16

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

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:~$

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

  • 12
    Это не настоящий CSV-файл - смотрите, как он записывается, если в данных есть запятые, поэтому использование встроенной поддержки COPY предпочтительнее. Но этот общий метод удобен для быстрого экспорта из Postgres в другие форматы с разделителями, кроме CSV.
13

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 с моего сервера без компиляции и/или установки инструмента.

  • 0
    Куда сохраняются результаты? Мой запрос выполняется, но файл не отображается нигде на моем компьютере. Вот что я делаю: COPY (выберите a, b из c, где d = '1'), ЧТОБЫ СОХРАНИТЬ С CSVHEADER> abcd.csv
  • 0
    @kRazzyR Выходные данные отправляются на стандартный вывод команды psql, поэтому в конечном итоге все, что вы делаете с использованием стандартного вывода, - это то, куда направляются данные. В моих примерах я использую «> file.csv» для перенаправления в файл. Вы хотите убедиться, что команда находится вне сервера, отправляемого через параметр psql -c. Смотрите пример «локального компьютера».
11

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

  • 0
    Ответ IMSoP не сработал для меня, так как мне нужно было быть супер-администратором. Это сработало. Спасибо!
10

Я работаю над 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
6

Я написал небольшой инструмент под названием 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
  • 0
    Работает отлично. Спасибо.
5

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

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

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

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

psql -d my_db_name -t -A -F";" -f input-file.sql -o output-file.csv
  • 0
    Я должен был использовать -F"," вместо -F";" создать файл CSV, который будет правильно открываться в MS Excel
1

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

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

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


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


Изображение 4044

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

0

Новая версия - 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
0

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

Copy (Select * From tableName) To '/tmp/fileName.csv' With CSV HEADER;
-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'
  • 3
    Пожалуйста, объясните, что вы сделали, редактируя ответ, избегая только кода ответа
  • 3
    Спасибо за этот фрагмент кода, который может предоставить некоторую ограниченную краткосрочную помощь. Правильное объяснение значительно улучшило бы его долгосрочную ценность, показав, почему это хорошее решение проблемы, и сделало бы его более полезным для будущих читателей с другими, похожими вопросами. Пожалуйста, измените свой ответ, чтобы добавить некоторые объяснения, в том числе предположения, которые вы сделали.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню