Як імпортувати дані файлів CSV в таблицю PostgreSQL?


601

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


18
Чому зберігається процедура? КОПІЙ робить трюк
Френк Хейкенс

1
У мене є інтерфейс користувача, який завантажує файл csv, для підключення цього мені потрібна збережена процедура, яка фактично копіює дані з файлу cvs
vardhan

3
Ви могли б детальніше розповісти про те, як використовувати КОПІЮ?
вардхан

17
Божидар Бацов уже дав вам посилання на приклад, чудовий посібник також може допомогти: postgresql.org/docs/8.4/interactive/sql-copy.html
Френк Хейкенс

Відповіді:


774

Погляньте на цю коротку статтю .


Тут перефразовано рішення:

Створіть свою таблицю:

CREATE TABLE zip_codes 
(ZIP char(5), LATITUDE double precision, LONGITUDE double precision, 
CITY varchar, STATE char(2), COUNTY varchar, ZIP_CLASS varchar);

Скопіюйте дані з CSV-файлу в таблицю:

COPY zip_codes FROM '/path/to/csv/ZIP_CODES.txt' WITH (FORMAT csv);

46
фактично використання \ copy зробить той самий трюк, якщо у вас немає доступу супер користувача; він скаржиться на мою Fedora 16 при використанні COPY з некореневим обліковим записом.
askw0rder

81
Порада: ви можете вказати, які стовпці у вас у CSV, використовуючи zip_codes (col1, col2, col3). Стовпці повинні бути вказані в тому ж порядку, що і у файлі.
Девід Пелаес

6
@ askw0rder чи \ copy має однаковий синтаксис? bcoz Я отримую синтаксичну помилку з \ copy
JhovaniC

6
Чи слід включати рядок заголовка?
bernie2436

116
Ви можете легко включити заголовок рядка - просто додайте HEADER у параметри: COPY zip_codes FROM '/path/to/csv/ZIP_CODES.txt' DELIMITER ',' CSV HEADER; postgresql.org/docs/9.1/static/sql-copy.html
Barrett Clark

221

Якщо у вас немає дозволу на використання COPY(які працюють на db-сервері), ви можете використовувати \copyзамість цього (який працює в db-клієнті). Використовуючи той же приклад, що і Божидар Бацов:

Створіть свою таблицю:

CREATE TABLE zip_codes 
(ZIP char(5), LATITUDE double precision, LONGITUDE double precision, 
CITY varchar, STATE char(2), COUNTY varchar, ZIP_CLASS varchar);

Скопіюйте дані з CSV-файлу в таблицю:

\copy zip_codes FROM '/path/to/csv/ZIP_CODES.txt' DELIMITER ',' CSV

Ви також можете вказати стовпці для читання:

\copy zip_codes(ZIP,CITY,STATE) FROM '/path/to/csv/ZIP_CODES.txt' DELIMITER ',' CSV

Дивіться документацію щодо КОПІЇ :

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

і зверніть увагу:

Для стовпців ідентичності команда COPY FROM завжди записуватиме значення стовпців, що містяться у вхідних даних, як опція INSERT НАДЗНАЧЕННЯ СИСТЕМИ СИСТЕМИ.


\ Скопіюйте виборців (ZIP, CITY) ВІД '/Users/files/Downloads/WOOD.TXT' DELIMITER ',' CSV HEADER; ПОМИЛКА: додаткові дані після останнього очікуваного стовпчика КОНТЕКСТ: КОПІЮВАННЯ виборців, рядок 2: "OH0012781511,87,26953, ДОМАШНИК, ШЕРРІ, ЛІЙСЬ, 11/26 / 1965,08 / 19/1988,, 211 N GARFIELD ST,, BLOOMD ... »
JZ.

@JZ. У мене була подібна помилка. Це було тому, що у мене були додаткові порожні стовпці. Перевірте свій csv, і якщо у вас є порожні стовпці, це може бути причиною.
Алекс Беннетт

5
Це дещо вводить в оману: різниця між COPYта \copyнабагато більше, ніж просто дозволи, і ви не можете просто додати ``, щоб він магічно працював. Дивіться опис (в контексті експорту) тут: stackoverflow.com/a/1517692/157957
IMSoP

@IMSoP: ти маєш рацію, я додав згадку про сервер і клієнта для уточнення
bjelli

@bjelli \ копіює повільніше, ніж копія? У мене є файл 1,5 МБ і екземпляр db.m4.large на RDS, і ця команда копіювання минула кілька годин (принаймні 3).
Себастьян

79

Швидкий спосіб зробити це за допомогою бібліотеки панд Python (найкраща версія версії 0.15 або вище). Це допоможе створити стовпці для вас, хоча, очевидно, вибір, який він робить для типів даних, може бути не таким, як вам потрібно. Якщо це не зовсім те, що ви хочете, ви завжди можете використовувати код 'create table', сформований як шаблон.

Ось простий приклад:

import pandas as pd
df = pd.read_csv('mypath.csv')
df.columns = [c.lower() for c in df.columns] #postgres doesn't like capitals or spaces

from sqlalchemy import create_engine
engine = create_engine('postgresql://username:password@localhost:5432/dbname')

df.to_sql("my_table_name", engine)

А ось код, який показує, як встановити різні параметри:

# Set it so the raw sql output is logged
import logging
logging.basicConfig()
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)

df.to_sql("my_table_name2", 
          engine, 
          if_exists="append",  #options are ‘fail’, ‘replace’, ‘append’, default ‘fail’
          index=False, #Do not output the index of the dataframe
          dtype={'col1': sqlalchemy.types.NUMERIC,
                 'col2': sqlalchemy.types.String}) #Datatypes should be [sqlalchemy types][1]

6
Крім того, if_existsпараметр можна встановити для заміни або додавання до існуючої таблиці, наприкладdf.to_sql("fhrs", engine, if_exists='replace')
joelostblom

1
ім'я користувача та пароль: потрібно створити логін та призначити БД користувачеві. Якщо використовується pgAdmin, тоді створіть "Роль для входу / групи" за допомогою GUI
Somnath Kadam

9
Pandas - це дуже повільний спосіб завантаження до sql (vs CSV файлів). Можуть бути на порядок повільнішими.
user48956

Це може бути спосіб запису даних, але це дуже повільно, навіть з пакетною та хорошою обчислювальною потужністю. Використання CSV - це хороший спосіб досягти цього.
Анкіт Сінгх

df.to_sql()це дуже повільно, ви можете використовувати d6tstack.utils.pd_to_psql()з d6tstack, дивіться порівняння продуктивності
citynorman

30

Ви також можете використовувати pgAdmin, який пропонує графічний інтерфейс для імпорту. Це показано в цій темі SO . Перевага використання pgAdmin полягає в тому, що він також працює для віддалених баз даних.

Як і в попередніх рішеннях, вам потрібно буде вже мати свою таблицю в базі даних. У кожної людини є власне рішення, але те, що я зазвичай роблю, це відкрити CSV в Excel, скопіювати заголовки, вставити спеціальні з переміщенням на інший робочий аркуш, розмістити відповідний тип даних у наступному стовпчику, а потім просто скопіювати та вставити його в текстовий редактор разом із відповідним запитом створення таблиці SQL так:

CREATE TABLE my_table (
    /*paste data from Excel here for example ... */
    col_1 bigint,
    col_2 bigint,
    /* ... */
    col_n bigint 
)

1
pls показують пару зразків рядків ваших вставлених даних
dcorking

29

Більшість інших рішень тут потребують створення таблиці заздалегідь / вручну. У деяких випадках це може бути не практично (наприклад, якщо у таблиці призначення багато стовпців). Отже, підхід нижче може стати корисним.

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

Передбачається, що у верхньому рядку є назви стовпців.

create or replace function data.load_csv_file
(
    target_table text,
    csv_path text,
    col_count integer
)

returns void as $$

declare

iter integer; -- dummy integer to iterate columns with
col text; -- variable to keep the column name at each iteration
col_first text; -- first column name, e.g., top left corner on a csv file or spreadsheet

begin
    create table temp_table ();

    -- add just enough number of columns
    for iter in 1..col_count
    loop
        execute format('alter table temp_table add column col_%s text;', iter);
    end loop;

    -- copy the data from csv file
    execute format('copy temp_table from %L with delimiter '','' quote ''"'' csv ', csv_path);

    iter := 1;
    col_first := (select col_1 from temp_table limit 1);

    -- update the column names based on the first row which has the column names
    for col in execute format('select unnest(string_to_array(trim(temp_table::text, ''()''), '','')) from temp_table where col_1 = %L', col_first)
    loop
        execute format('alter table temp_table rename column col_%s to %s', iter, col);
        iter := iter + 1;
    end loop;

    -- delete the columns row
    execute format('delete from temp_table where %s = %L', col_first, col_first);

    -- change the temp table name to the name given as parameter, if not blank
    if length(target_table) > 0 then
        execute format('alter table temp_table rename to %I', target_table);
    end if;

end;

$$ language plpgsql;

1
Привіт Мехмете, дякую за відповідь, яку ви опублікували, але коли я запускаю ваш код, я отримую таке повідомлення про помилку: ПОМИЛКА: схема "дані" не існує
користувач2867432

user2867432 вам потрібно змінити ім'я схеми, яке ви використовуєте відповідно (наприклад, public)
mehmet

Привіт Мехмете, спасибі за рішення, це ідеально, але це працює лише в тому випадку, якщо користувач DB Postgres є суперрусером, чи є який-небудь спосіб змусити його працювати без суперпользователя?
Geeme

Geeme: читати «Визначник безпеки» тут , але я не використовував його сам.
mehmet

Прекрасна відповідь! Я не збираюся надто загальним, хоча в своєму коді для читабельності для інших.
Манохар Редді Поредді

19

Як згадував Пол, імпорт працює в pgAdmin:

клацніть правою кнопкою миші на таблиці -> імпорт

виберіть локальний файл, формат та кодування

ось скріншот німецького графічного інтерфейсу pgAdmin:

pgAdim Імпорт GUI

подібне, що ви можете зробити з DbVisualizer (у мене є ліцензія, не впевнений у вільній версії)

клацніть правою кнопкою миші на таблиці -> Імпортувати дані таблиці ...

Графічний інтерфейс імпорту DbVisualizer


2
Імпортувати DBVisualizer потрібно 50 секунд, щоб імпортувати 1400 рядків з трьома полями - і мені довелося перекинути все назад від String до того, що він мав бути.
Номенон


10
  1. Спершу створіть таблицю

  2. Потім скопіюйте команду copy, щоб скопіювати дані таблиці:

скопіювати ім'я_на_відділу (C1, C2, C3 ....)
з 'шлях до вашого файлу CSV' роздільник ',' заголовка csv;

Дякую


3
Як це не прийнята відповідь? Навіщо мені писати сценарій python, коли база даних вже має команду для цього?
Уес


8

Особистий досвід роботи з PostgreSQL, який все ще чекає швидшого шляху.

1. Створіть скелет таблиці спочатку, якщо файл зберігається локально:

    drop table if exists ur_table;
    CREATE TABLE ur_table
    (
        id serial NOT NULL,
        log_id numeric, 
        proc_code numeric,
        date timestamp,
        qty int,
        name varchar,
        price money
    );
    COPY 
        ur_table(id, log_id, proc_code, date, qty, name, price)
    FROM '\path\xxx.csv' DELIMITER ',' CSV HEADER;

2. Коли \ path \ xxx.csv знаходиться на сервері, postgreSQL не має дозволу на доступ до сервера, вам доведеться імпортувати .csv файл через вбудований функціонал pgAdmin.

Клацніть правою кнопкою миші назву таблиці та виберіть імпорт.

введіть тут опис зображення

Якщо у вас все ще виникають проблеми, зверніться до цього посібника. http://www.postgresqltutorial.com/import-csv-file-into-posgresql-table/


6

Як імпортувати дані файлів CSV в таблицю PostgreSQL?

кроки:

  1. Потрібно підключити базу даних postgresql в терміналі

    psql -U postgres -h localhost
  2. Потрібно створити базу даних

    create database mydb;
  3. Потрібно створити користувача

    create user siva with password 'mypass';
  4. Підключення до бази даних

    \c mydb;
  5. Потрібно створити схему

    create schema trip;
  6. Потрібно створити таблицю

    create table trip.test(VendorID int,passenger_count int,trip_distance decimal,RatecodeID int,store_and_fwd_flag varchar,PULocationID int,DOLocationID int,payment_type decimal,fare_amount decimal,extra decimal,mta_tax decimal,tip_amount decimal,tolls_amount int,improvement_surcharge decimal,total_amount
    );
  7. Імпортуйте дані файлу CSV у postgresql

    COPY trip.test(VendorID int,passenger_count int,trip_distance decimal,RatecodeID int,store_and_fwd_flag varchar,PULocationID int,DOLocationID int,payment_type decimal,fare_amount decimal,extra decimal,mta_tax decimal,tip_amount decimal,tolls_amount int,improvement_surcharge decimal,total_amount) FROM '/home/Documents/trip.csv' DELIMITER ',' CSV HEADER;
  8. Знайдіть дані таблиці

    select * from trip.test;

5

IMHO, найзручніший спосіб - це дотримуватися " Імпортувати CSV-дані в postgresql, зручним способом ;-) ", використовуючи csvsql від csvkit , який є пакетом python, який можна встановити через pip.


3
Гниль посилань ненажерлива! Стаття, з якою ви посилаєтесь, більше не працює, і це мені незручно :(
chbrown

Ви можете сказати, що його пі.
гірський альпініст

1
Для мене я отримую MemoryError, якщо намагаюся імпортувати великий CSV, щоб він виглядав так, що він не передається.
DavidC

@DavidC Цікаво. Наскільки великий ваш файл? Скільки у вас пам’яті? Якщо він не потік , як це здається, я пропоную відриви даних перед вставленим
ділянку

1
Файл був розміром 5 ГБ і в мене є 2 Гб пам'яті. Я відмовився від цього і застосував сценарій для створення команд CREATE TABLE та COPY врешті-решт.
DavidC

3

У Python ви можете використовувати цей код для автоматичного створення таблиці PostgreSQL з іменами стовпців:

import pandas, csv

from io import StringIO
from sqlalchemy import create_engine

def psql_insert_copy(table, conn, keys, data_iter):
    dbapi_conn = conn.connection
    with dbapi_conn.cursor() as cur:
        s_buf = StringIO()
        writer = csv.writer(s_buf)
        writer.writerows(data_iter)
        s_buf.seek(0)
        columns = ', '.join('"{}"'.format(k) for k in keys)
        if table.schema:
            table_name = '{}.{}'.format(table.schema, table.name)
        else:
            table_name = table.name
        sql = 'COPY {} ({}) FROM STDIN WITH CSV'.format(table_name, columns)
        cur.copy_expert(sql=sql, file=s_buf)

engine = create_engine('postgresql://user:password@localhost:5432/my_db')

df = pandas.read_csv("my.csv")
df.to_sql('my_table', engine, schema='my_schema', method=psql_insert_copy)

Це також відносно швидко, я можу імпортувати понад 3,3 мільйона рядків приблизно за 4 хвилини.


2

Ви також можете використовувати pgfutter або, ще краще, pgcsv .

pgfutter досить баггі, рекомендую pgcsv.

Ось як це зробити за допомогою pgcsv:

sudo pip install pgcsv
pgcsv --db 'postgresql://localhost/postgres?user=postgres&password=...' my_table my_file.csv

1

Якщо вам потрібен простий механізм імпорту з текстового / розбору багаторядкового CSV, ви можете використовувати:

CREATE TABLE t   -- OR INSERT INTO tab(col_names)
AS
SELECT
   t.f[1] AS col1
  ,t.f[2]::int AS col2
  ,t.f[3]::date AS col3
  ,t.f[4] AS col4
FROM (
  SELECT regexp_split_to_array(l, ',') AS f
  FROM regexp_split_to_table(
$$a,1,2016-01-01,bbb
c,2,2018-01-01,ddd
e,3,2019-01-01,eee$$, '\n') AS l) t;

Демонстрація DBFiddle


1

DBeaver Community Edition (dbeaver.io) робить тривіальним підключення до бази даних, а потім імпортує файл CSV для завантаження в базу даних PostgreSQL. Це також дозволяє легко видавати запити, отримувати дані та завантажувати набори результатів у CSV, JSON, SQL чи інші поширені формати даних.

Це багатоплатформенний засіб баз даних FOSS для програмістів SQL, DBA та аналітики, який підтримує всі популярні бази даних: MySQL, PostgreSQL, SQLite, Oracle, DB2, SQL Server, Sybase, MS Access, Teradata, Firebird, Hive, Presto тощо. Це життєздатний конкурент FOSS TOAD для Postgres, TOAD для SQL Server або Toad for Oracle.

Я не маю приналежності до DBeaver. Мені подобається ціна (БЕЗКОШТОВНА!) Та повна функціональність, але я б хотів, щоб вони більше відкривали цей додаток DBeaver / Eclipse і полегшували додавання віджетів аналітики до DBeaver / Eclipse, а не вимагати від користувачів плати за щорічну підписку в 199 доларів просто створювати графіки та діаграми безпосередньо в додатку. Мої навички кодування Java іржавіють, і мені не хочеться витрачати тижні, щоб дізнатися, як створювати віджети Eclipse (лише щоб виявити, що DBeaver, ймовірно, відключив можливість додавати сторонні віджети до DBeaver Community Edition.)

Чи можуть користувачі енергії DBeaver, які є розробниками Java, надавати деяку інформацію про кроки створення віджетів аналітики, які потрібно додати до спільноти DBeaver Edition?


Було б добре зрозуміти, як насправді використовувати DBeaver для імпорту CSV-файлу. У будь-якому випадку це може допомогти: dbeaver.com/docs/wiki/Data-transfer
umbe1987

0

Створіть таблицю та встановіть потрібні стовпці, які використовуються для створення таблиці у файлі csv.

  1. Відкрийте postgres і клацніть правою кнопкою миші на цільовій таблиці, яку ви хочете завантажити та вибрати імпорт та оновіть наступні кроки в розділі параметрів файлів

  2. Тепер перегляньте свій файл у назві файлу

  3. Виберіть формат csv

  4. Кодування як ISO_8859_5

Тепер goto Misc. параметри та перевірте заголовок та натисніть на імпорт.


0

Я створив невеликий інструмент, який імпортує csvфайл у PostgreSQL super easy, просто команда, і він буде створювати та заповнювати таблиці, на жаль, на даний момент усі створені поля автоматично використовують тип TEXT

csv2pg users.csv -d ";" -H 192.168.99.100 -U postgres -B mydatabase

Засіб можна знайти на https://github.com/eduardonunesp/csv2pg


Ви створили окремий інструмент для еквівалента psql -h 192.168.99.100 -U postgres mydatabase -c "COPY users FROM 'users.csv' DELIMITER ';' CSV"? Я здогадуюсь, частина, де вона створює таблицю, приємна, але оскільки кожне поле - це текст, це не надто корисно
GammaGames

1
Ой, дякую за голови вгору. Так, я це зробив, ну, це зайняло всього кілька годин, і я дізнався класні речі в Go і pq та API бази даних в Go.
Едуардо Перейра
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.