Как импортировать данные файла CSV в таблицу PostgreSQL?


602

Как я могу написать хранимую процедуру, которая импортирует данные из файла CSV и заполняет таблицу?


18
Почему хранимая процедура? COPY делает
свое дело

1
У меня есть пользовательский интерфейс, который загружает файл CSV, чтобы подключить это мне нужна хранимая процедура, которая на самом деле копирует данные из файла CVS
vardhan

3
не могли бы вы рассказать о том, как использовать COPY?
Вардан

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

Ответы:


775

Посмотрите на эту короткую статью .


Решение перефразировано здесь:

Создайте свою таблицу:

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 с учетной записью без полномочий root.
asksw0rder

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

6
@ asksw0rder имеет ли \ 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
Баррет Кларк,

222

Если у вас нет разрешения на использование COPY(которое работает на сервере БД), вы можете использовать \copyвместо этого (которое работает в клиенте БД). Используя тот же пример, что и Божидар Бацов:

Создайте свою таблицу:

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 :

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

и обратите внимание:

Для столбцов идентификаторов команда COPY FROM всегда записывает значения столбцов, указанные во входных данных, например параметр INSERT OVERRIDING SYSTEM VALUE.


\ копировать избирателей (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, то создайте «Login / Group роль» с помощью графического интерфейса
Сомнатх Кадам

9
Pandas - это очень медленный способ загрузки в sql (по сравнению с CSV-файлами). Может быть на несколько порядков медленнее.
user48956

Это может быть способ записи данных, но он очень медленный даже при пакетной работе и хорошей вычислительной мощности. Использование CSV - хороший способ сделать это.
Анкит Сингх

df.to_sql()очень медленно, вы можете использовать d6tstack.utils.pd_to_psql()из d6tstack посмотреть сравнение производительности
citynorman

30

Вы также можете использовать pgAdmin, который предлагает графический интерфейс для импорта. Это показано в этой теме . Преимущество использования 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
Пожалуйста, покажите несколько примеров строк ваших вставленных данных
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
Привет, Мехмет, спасибо за ответ, который ты выложил, но когда я запускаю твой код, я получаю следующее сообщение об ошибке: ОШИБКА: схема "data" не существует
user2867432

user2867432 вам нужно изменить имя схемы, которое вы используете соответственно (например, public)
mehmet

Привет, Мехмет, спасибо за решение, это прекрасно, но это работает, только если пользователь postgres DB суперпользователь, есть ли способ заставить его работать без суперпользователя?
Джим

Geeme: прочитайте «определитель безопасности» здесь , но я не использовал его сам.
Мехмет

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

19

Как упоминал Пол, импорт работает в pgAdmin:

щелкните правой кнопкой мыши по таблице -> импорт

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

вот немецкий скриншот pgAdmin GUI:

pgAdmin импорт графического интерфейса

То же самое вы можете сделать с DbVisualizer (у меня есть лицензия, но я не уверен насчет бесплатной версии)

щелкните правой кнопкой мыши таблицу -> Импортировать данные таблицы ...

DbVisualizer импорт GUI


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


10
  1. сначала создайте таблицу

  2. Затем используйте команду copy, чтобы скопировать данные таблицы:

скопировать имя_таблицы (C1, C2, C3 ....)
из 'path to your csv file' delimiter ',' csv header;

Спасибо


3
Как это не принятый ответ? Зачем мне писать скрипт на python, если в базе данных уже есть команда для этого?
Уэс

8

Используйте этот код SQL

    copy table_name(atribute1,attribute2,attribute3...)
    from 'E:\test.csv' delimiter ',' csv header

ключевое слово header позволяет СУБД знать, что файл csv имеет заголовок с атрибутами

для получения дополнительной информации посетите http://www.postgresqltutorial.com/import-csv-file-into-posgresql-table/


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

ИМХО, наиболее удобный способ - следовать « Импортировать данные CSV в postgresql, удобный способ ;-) », используя csvsql из csvkit , который представляет собой пакет python, устанавливаемый через pip.


3
Ссылка гниль прожорлива! Статья, на которую вы
ссылаетесь,

Вы могли бы упомянуть, что его зовут.
горный альпинист

1
Для меня я получаю MemoryError, если пытаюсь импортировать большой CSV-файл, чтобы он не передавался в потоковом режиме.
DavidC

@DavidC Интересно. Насколько большой ваш файл? Сколько у тебя памяти? Если он не передается так, как кажется, я предлагаю разделить данные перед вставкой
sal

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 Demo


1

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

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

Я не имею никакого отношения к DBeaver. Мне нравится цена (БЕСПЛАТНО!) И полная функциональность, но я бы хотел, чтобы они больше открывали это приложение DBeaver / Eclipse и позволяли легко добавлять аналитические виджеты в DBeaver / Eclipse, а не требовать от пользователей платить за годовую подписку всего в 199 долларов. создавать графики и диаграммы непосредственно в приложении. Мои навыки Java-кодирования устарели, и я не хочу потратить недели на то, чтобы заново научиться создавать виджеты Eclipse (только чтобы обнаружить, что DBeaver, вероятно, отключил возможность добавления сторонних виджетов в DBeaver Community Edition.)

Могут ли опытные пользователи DBeaver, которые являются разработчиками Java, дать некоторое представление о шагах по созданию аналитических виджетов для добавления в Community Edition DBeaver?


Было бы неплохо понять, как на самом деле использовать DBeaver для импорта файла CSV. В любом случае, это может помочь: dbeaver.com/docs/wiki/Data-transfer
umbe1987

0

Создать таблицу и иметь обязательные столбцы, которые используются для создания таблицы в CSV-файле.

  1. Откройте postgres и щелкните правой кнопкой мыши на целевой таблице, которую вы хотите загрузить, и выберите импорт и обновите следующие шаги в разделе параметров файла.

  2. Теперь просмотрите ваш файл в имени файла

  3. Выберите CSV в формате

  4. Кодировка как ISO_8859_5

Теперь перейдите на доп. Параметры и проверьте заголовок и нажмите на импорт.


0

Я создал небольшой инструмент, который csvочень легко импортирует файл в PostgreSQL, просто команду, которая будет создавать и заполнять таблицы, к сожалению, в настоящий момент все автоматически созданные поля используют тип 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.