Збережіть вихід PL / pgSQL з PostgreSQL у файл CSV


Відповіді:


1367

Ви хочете отриманий файл на сервері чи на клієнті?

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

Якщо ви хочете щось легко використати або автоматизувати, ви можете використовувати вбудовану команду COPY Postgresql . напр

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

Цей підхід працює повністю на віддаленому сервері - він не може записувати на ваш локальний ПК. Його також потрібно запускати як "суперпользователь" Postgres (зазвичай його називають "root"), оскільки Postgres не може зупинити його робити неприємні дії з локальною файловою системою цієї машини.

Це на самому ділі не означає , що ви повинні бути підключені як привілейований користувач (автоматизації , що буде представляти загрозу безпеці іншого роду), тому що ви можете використовувати в SECURITY DEFINERможливістьCREATE FUNCTION зробити функцію , яка працює , як якщо б ви були суперкористувача .

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

  1. Які файли слід дозволити користувачеві читати / писати на диску? Наприклад, це може бути конкретний каталог, а ім'я файлу може мати відповідний префікс або розширення.
  2. Які таблиці повинен користувач може читати / писати в базі даних? Зазвичай це визначається GRANTs в базі даних, але функція зараз працює як суперпользователь, тому таблиці, які зазвичай не знаходяться ", будуть повністю доступними. Напевно, ви не хочете, щоб хтось посилався на вашу функцію та додавав рядки в кінці таблиці ваших користувачів ...

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


Сторона клієнта

Інший підхід - це обробка файлів на стороні клієнта , тобто у вашій програмі чи сценарії. Серверу Postgres не потрібно знати, у який файл ви копіюєте, він просто виплює дані, і клієнт десь розміщує їх.

Основним синтаксисом для цього є COPY TO STDOUTкоманда, а графічні інструменти, такі як pgAdmin, перетягнуть її в хороший діалог.

psqlКлієнт командного рядка має спеціальний «мета-команду» під назвою \copy, який приймає всі ті ж параметри , як «реальні» COPY, але запускається всередині клієнта:

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

Зауважте, що немає завершення ;, оскільки метакоманди завершуються новим рядком, на відміну від команд SQL.

З документів :

Не плутати COPY з інструкцією psql \ copy. \ копіює виклики COPY OF STDIN або COPY TO STDOUT, а потім отримує / зберігає дані у файлі, доступному клієнту psql. Таким чином, доступність файлів та права доступу залежать від клієнта, а не від сервера, коли використовується \ copy.

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


131
Очевидно, що вище приклад вимагає, щоб користувач іноді був супер-користувачем, ось версія для звичайних людей;) відлуння "КОПІЯ (ВИБІР * від foo) НА ПОВЕРНЕННЯ з CSV HEADER" | psql -o '/tmp/test.csv' database_name
Drachenfels

10
@Drachenfels: \copyтеж працює - там шляхи відносно клієнта, і крапка з комою не потрібна / дозволена. Дивіться мою редакцію.
krlmlr

3
@IMSoP: Як би ви додали оператор COPY до функції sql (на postgres 9.3)? Отже запит зберігається у .csv-файлі?
jO.

12
Схоже, \copyпотрібно бути однолінійним. Таким чином, ви не отримаєте красу форматування sql так, як вам потрібно, а просто помістіть навколо нього копію / функцію.
isaaclw

1
@AndreSilva Як говориться у відповіді, \copyце спеціальна мета-команда в psqlклієнтському командному рядку . Він не працюватиме в інших клієнтах, таких як pgAdmin; вони, можливо, матимуть власні інструменти, такі як графічні майстри, для виконання цієї роботи.
IMSoP

519

Є кілька рішень:

1 psqlкоманда

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

Це має велику перевагу в тому, що ви можете користуватися ним через SSH, наприклад, ssh postgres@host command- це дозволяє вам отримати

2 copyкоманда postgres

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, але це не можливо для написання сценарію.


32
Перший варіант IMHO - це схильність до помилок, оскільки він не включає належне виведення коми з експортованих даних.
Піохен

4
Крім того, psql не вказує значення комірок, тому якщо БУДЬ-який із ваших даних використовує роздільник, ваш файл буде пошкоджений.
Серін

7
@Cerin -t є синонімом для --tuples-only (вимкніть друк імен стовпців та підрахунків колонок рядків результатів тощо) - пропустіть його, щоб отримати заголовки стовпців
ic3b3rg

21
Щойно перевірене твердження, що ухиляється від коми - це правда, метод №1 не уникає коми у значеннях.
MrColes

1
також використовуйте "\ pset footer", щоб кількість рядків не
мочилася

94

У терміналі (при підключенні до 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
і \ o для того, щоб знову надрукувати консоль
metdos

2
Це не створить файл CSV, він просто запише командний висновок у текстовий файл (що не робить його розділеним комою).
Руслан Кабалін

@RuslanKabalin Так, я щойно помітив це і допоміг інструкцію щодо створення виходу, розділеного комами (cvs)
Marcin Wasiluk

5
Я б вдосконалив цю відповідь, зазначивши, що вихід csv не буде належним чином виконаний, і кожен раз, коли виконується команда sql, результати приєднуються до вихідного файлу.
Денні Армстронг

А як щодо нових рядків у значеннях поля? Інструкції COPYабо \copyпідходять правильно (перетворюють у стандартний формат CSV); це робить?
Wildcard

37

Якщо вас цікавлять усі стовпці певної таблиці разом із заголовками, ви можете використовувати

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

Це крихітно трохи простіше, ніж

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

які, наскільки мені відомо, рівнозначні.


1
Якщо запит є звичайним (у IE, що має псевдоніми стовпців або приєднуються до різних таблиць), заголовок буде друкувати псевдоніми стовпців так само, як він відображається на екрані.
Devy

33

Об’єднання експорту CSV

Ця інформація насправді недостатньо представлена. Оскільки це вже другий раз, коли мені потрібно було це зробити, я поставлю це тут, щоб нагадати про себе, якщо нічого іншого.

Дійсно, найкращий спосіб зробити це (вивести CSV з постгресів) - використовувати 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

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


1
Де зберігаються результати? Мій запит працює, але файл не з’являється ніде на моєму комп’ютері. Це те, що я роблю: КОПІРУЙТЕ (виберіть a, b з c, де d = '1'), ЩО ВИБІРАТИ З CSVHEADER> abcd.csv
kRazzy R

1
@kRazzyR Вихід йде на stdout команди psql, тому в кінцевому підсумку все, що ви робите зі stdout, - це куди йдуть дані. У своїх прикладах я використовую '> file.csv' для переадресації у файл. Ви хочете переконатися, що воно знаходиться поза межами команди, що надсилається на сервер через параметр psql -c. Дивіться приклад "локальної машини".
joshperry

Дякую за повне пояснення. Команда копіювання безнадійно складна з psql. Зазвичай я використовую безкоштовний клієнт бази даних (dbeaver Community Edition) для імпорту та експорту файлів даних. Він надає хороші інструменти для картографування та форматування. Ваша відповідь надає чудові детальні приклади копіювання з віддалених систем.
Багатий доктор фізичних наук

24

Мені довелося використовувати \ 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;

і воно функціонує


17

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.
Грег Сміт

16

Я працюю над 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

16

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

11

У pgAdmin III є можливість експорту у файл із вікна запиту. У головному меню це Query -> Execute to file або є кнопка, яка робить те саме (це зелений трикутник із синьою дискетою на відміну від звичайного зеленого трикутника, який просто виконує запит). Якщо ви не запускаєте запит у вікні запиту, я б зробив те, що запропонував IMSoP, і скористався командою копіювання.


Відповідь IMSoP не працювала для мене, оскільки мені потрібно було бути супер адміністратором. Це спрацювало частування. Дякую!
Майк

9

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

Ось що для мене спрацювало.

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

9

Я написав невеликий інструмент під назвою, 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

2
Чудово працює. Дякую.
AlexM

6

Якщо у вас є більш тривалий запит, і ви хочете використовувати psql, тоді поставте свій запит у файл і скористайтеся такою командою:

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

FWIW, мені довелося використовувати -F","замість того, -F";"щоб генерувати файл CSV, який би відкрився правильно у MS Excel
CFL_Jeff

4

Щоб завантажити файл CSV з іменами стовпців як HEADER, використовуйте цю команду:

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

1

Я дуже рекомендую DataGrip , IDE бази даних від JetBrains. Ви можете експортувати SQL-запит у файл CSV та легко налаштувати ssh-тунелювання. Коли документація посилається на "набір результатів", вони означають результат, повернений запитом SQL в консолі.

Я не пов'язаний з DataGrip, я просто люблю продукт!


Я здогадуюсь, що зниження результату було пов'язане з відсутністю контексту / пояснення, тому я пов'язав з документацією DataGrip. Якщо є інша причина проти голосування, будь ласка, повідомте мене про це. Я використовував рішення CLI вище, і DataGrip набагато простіше для менших запитів.
skeller88

Проблема з DataGrip полягає в тому, що він утримує ваш гаманець. Це не безкоштовно. Спробуйте спільне видання DBeaver на dbeaver.io . Це багатоплатформенний засіб баз даних FOSS для програмістів SQL, DBA та аналітиків, який підтримує всі популярні бази даних: MySQL, PostgreSQL, SQLite, Oracle, DB2, SQL Server, Sybase, MS Access, Teradata, Firebird, Hive, Presto тощо.
Багатий доктор фізичних наук

Класно, я перевірю це. Як щодо того, що ви також репостуєте коментар як відповідь?
skeller88

0

JackDB , клієнт бази даних у вашому веб-браузері, робить це дуже просто. Особливо, якщо ти на Хероку.

Він дозволяє підключатися до віддалених баз даних і запускати на них SQL запити.

                                                                                                                                                       Джерело (джерело: jackdb.com )jackdb-heroku


Після підключення БД ви можете запустити запит та експортувати в CSV або TXT (див. Праворуч внизу).


jackdb-експорт

Примітка. Я жодним чином не пов'язаний з JackDB. Зараз я користуюся їхніми безкоштовними послугами і думаю, що це чудовий продукт.


0

На запит @ skeller88 я надсилаю свій коментар як відповідь, щоб люди не втрачали кожної відповіді ...

Проблема з DataGrip полягає в тому, що він утримує ваш гаманець. Це не безкоштовно. Спробуйте спільне видання DBeaver на dbeaver.io. Це багатоплатформенний засіб баз даних FOSS для програмістів SQL, DBA та аналітиків, який підтримує всі популярні бази даних: MySQL, PostgreSQL, SQLite, Oracle, DB2, SQL Server, Sybase, MS Access, Teradata, Firebird, Hive, Presto тощо.

DBeaver Community Edition робить тривіальним підключення до бази даних, видавати запити для отримання даних, а потім завантажувати набір результатів, щоб зберегти їх у CSV, JSON, SQL або інших поширених форматах даних. Це життєздатний конкурент FOSS TOAD для Postgres, TOAD для SQL Server або Toad for Oracle.

Я не маю приналежності до DBeaver. Мені подобається ціна та функціональність, але я б хотів, щоб вони більше відкривали додаток DBeaver / Eclipse і полегшували додавання віджетів аналітики до DBeaver / Eclipse, а не вимагати від користувачів плати за щорічну підписку для створення графіків та діаграм безпосередньо в межах додаток. Мої навички кодування Java іржавіють, і мені не хочеться витрачати тижні, щоб вивчити, як створювати віджети Eclipse, лише щоб виявити, що DBeaver відключив можливість додавання сторонніх віджетів до DBeaver Community Edition.

Чи мають користувачі DBeaver розуміння кроків для створення віджетів аналітики для додавання до спільноти DBeaver Community?


-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
Поясніть, будь ласка, що ви зробили на редагування відповіді, уникайте лише відповіді на код
GGO

3
Дякуємо за цей фрагмент коду, який може надати деяку короткочасну допомогу. Правильне пояснення значно покращило б його довгострокове значення, показавши, чому це хороше рішення проблеми, і зробило б кориснішим майбутнім читачам інші подібні питання. Будь ласка , змініть свій відповідь , щоб додати деякі пояснення, в тому числі припущень , які ви зробили.
Toby Speight

2
Це створить файл json, а не файл csv.
nvoigt
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.