Wie importiere ich CSV-Dateidaten in eine PostgreSQL-Tabelle?

601

Wie kann ich eine gespeicherte Prozedur schreiben, die Daten aus einer CSV-Datei importiert und die Tabelle auffüllt?

Vardhan
quelle
18
Warum eine gespeicherte Prozedur? COPY macht den Trick
Frank Heikens
1
Ich habe eine Benutzeroberfläche, die die CSV-Datei hochlädt, um dies zu verbinden, brauche ich die gespeicherte Prozedur, die tatsächlich die Daten aus der Lebenslauf-Datei
kopiert
3
Können Sie näher erläutern, wie Sie die KOPIE verwenden?
Vardhan
17
Bozhidar Batsov hat Ihnen bereits einen Link zu einem Beispiel gegeben, das feine Handbuch könnte auch helfen: postgresql.org/docs/8.4/interactive/sql-copy.html
Frank Heikens
5
Aktuelles Handbuch: postgresql.org/docs/current/static/sql-copy.html
Basil Bourque

Antworten:

774

Schauen Sie sich diesen kurzen Artikel an .


Lösung hier umschrieben:

Erstellen Sie Ihre Tabelle:

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

Kopieren Sie Daten aus Ihrer CSV-Datei in die Tabelle:

COPY zip_codes FROM '/path/to/csv/ZIP_CODES.txt' WITH (FORMAT csv);
Bozhidar Batsov
quelle
46
Die Verwendung von \ copy würde den gleichen Trick ausführen, wenn Sie nicht über den Superuser-Zugriff verfügen. Es beschwert sich auf meinem Fedora 16, wenn COPY mit einem Nicht-Root-Konto verwendet wird.
fragt
81
TIPP: Mit den Postleitzahlen (col1, col2, col3) können Sie angeben, welche Spalten in der CSV enthalten sind. Die Spalten müssen in derselben Reihenfolge aufgelistet sein, in der sie in der Datei angezeigt werden.
David Pelaez
6
@ askw0rder hat \ copy die gleiche Syntax? bcoz Ich bekomme einen Syntaxfehler mit \ copy
JhovaniC
6
Soll ich die Kopfzeile einfügen?
Bernie2436
116
Sie können die Kopfzeile einfach COPY zip_codes FROM '/path/to/csv/ZIP_CODES.txt' DELIMITER ',' CSV HEADER; einfügen
Barrett Clark
222

Wenn Sie keine Berechtigung zur Verwendung haben COPY(die auf dem Datenbankserver funktioniert), können Sie \copystattdessen verwenden (was auf dem Datenbankclient funktioniert). Verwenden Sie das gleiche Beispiel wie Bozhidar Batsov:

Erstellen Sie Ihre Tabelle:

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

Kopieren Sie Daten aus Ihrer CSV-Datei in die Tabelle:

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

Sie können auch die zu lesenden Spalten angeben:

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

Siehe die Dokumentation zu COPY :

Verwechseln Sie COPY nicht mit der psql-Anweisung \ copy. \ copy ruft COPY FROM STDIN oder COPY TO STDOUT auf und ruft die Daten in einer Datei ab, auf die der psql-Client zugreifen kann. Daher hängen der Dateizugriff und die Zugriffsrechte eher vom Client als vom Server ab, wenn \ copy verwendet wird.

und Anmerkung:

Bei Identitätsspalten schreibt der Befehl COPY FROM immer die in den Eingabedaten angegebenen Spaltenwerte, wie z. B. die Option INSERT OVERRIDING SYSTEM VALUE.

bjelli
quelle
\ Wähler kopieren (ZIP, CITY) FROM '/Users/files/Downloads/WOOD.TXT' DELIMITER ',' CSV HEADER; FEHLER: zusätzliche Daten nach der zuletzt erwarteten Spalte KONTEXT: COPY-Wähler, Zeile 2: "OH0012781511,87,26953, HAUSHALTER, SHERRY, LEIGH ,, 26.11.1965,08 / 19/1988, 211 N GARFIELD ST ,, BLOOMD ... "
JZ.
@JZ. Ich hatte einen ähnlichen Fehler. Es war, weil ich extra leere Spalten hatte. Überprüfen Sie Ihre CSV und wenn Sie leere Spalten haben, könnte dies der Grund sein.
Alex Bennett
5
Dies ist etwas irreführend: Der Unterschied zwischen COPYund \copyist viel mehr als nur Berechtigungen, und Sie können nicht einfach ein `` hinzufügen, damit es magisch funktioniert. Siehe die Beschreibung (im Zusammenhang mit dem Export) hier: stackoverflow.com/a/1517692/157957
IMSoP
@IMSoP: Sie haben Recht, ich habe eine Erwähnung von Server und Client hinzugefügt, um
dies
@bjelli ist \ copy langsamer als copy? Ich habe eine 1,5-MB-Datei und eine db.m4.large-Instanz auf RDS und es sind Stunden vergangen, in denen dieser Kopierbefehl ausgeführt wurde (mindestens 3).
Sebastian
79

Eine schnelle Möglichkeit hierfür ist die Python-Pandas-Bibliothek (Version 0.15 oder höher funktioniert am besten). Auf diese Weise werden die Spalten für Sie erstellt - obwohl die Auswahlmöglichkeiten für Datentypen möglicherweise nicht Ihren Wünschen entsprechen. Wenn es nicht ganz das tut, was Sie wollen, können Sie immer den als Vorlage generierten Code "Tabelle erstellen" verwenden.

Hier ist ein einfaches Beispiel:

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)

Und hier ist ein Code, der Ihnen zeigt, wie Sie verschiedene Optionen einstellen:

# 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]
RobinL
quelle
6
Darüber hinaus kann der if_existsParameter so eingestellt werden, dass er eine vorhandene Tabelle ersetzt oder df.to_sql("fhrs", engine, if_exists='replace')
joelostblom
1
Benutzername und Passwort: Sie müssen sich anmelden und dem Benutzer eine Datenbank zuweisen. Wenn Sie pgAdmin verwenden, erstellen Sie "Anmelde- / Gruppenrolle" über die GUI
Somnath Kadam
9
Pandas ist eine super langsame Methode zum Laden in SQL (im Vergleich zu CSV-Dateien). Kann um Größenordnungen langsamer sein.
user48956
Dies könnte eine Möglichkeit sein, Daten zu schreiben, ist aber selbst bei Batch- und guter Rechenleistung sehr langsam. Die Verwendung von CSVs ist ein guter Weg, um dies zu erreichen.
Ankit Singh
df.to_sql()ist wirklich langsam, können Sie d6tstack.utils.pd_to_psql()von d6tstack verwenden, um Leistungsvergleich zu sehen
citynorman
30

Sie können auch pgAdmin verwenden, das eine grafische Benutzeroberfläche für den Import bietet. Das wird in diesem SO-Thread gezeigt . Der Vorteil der Verwendung von pgAdmin besteht darin, dass es auch für entfernte Datenbanken funktioniert.

Ähnlich wie bei den vorherigen Lösungen müssten Sie Ihre Tabelle jedoch bereits in der Datenbank haben. Jede Person hat ihre eigene Lösung, aber normalerweise öffne ich die CSV in Excel, kopiere die Überschriften, füge Special mit Transposition in ein anderes Arbeitsblatt ein, platziere den entsprechenden Datentyp in der nächsten Spalte und kopiere ihn einfach und füge ihn in einen Texteditor ein zusammen mit der entsprechenden SQL-Tabellenerstellungsabfrage wie folgt:

CREATE TABLE my_table (
    /*paste data from Excel here for example ... */
    col_1 bigint,
    col_2 bigint,
    /* ... */
    col_n bigint 
)
Paul
quelle
1
Bitte zeigen Sie ein paar Beispielzeilen Ihrer eingefügten Daten
dcorking
29

Die meisten anderen Lösungen hier erfordern, dass Sie die Tabelle im Voraus / manuell erstellen. Dies ist in einigen Fällen möglicherweise nicht praktikabel (z. B. wenn die Zieltabelle viele Spalten enthält). Der folgende Ansatz kann daher nützlich sein.

Wenn Sie den Pfad und die Spaltenanzahl Ihrer CSV-Datei angeben, können Sie die folgende Funktion verwenden, um Ihre Tabelle in eine temporäre Tabelle zu laden, die wie folgt benannt wird target_table:

Es wird angenommen, dass die oberste Zeile die Spaltennamen enthält.

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;
mehmet
quelle
1
Hallo Mehmet, danke für die Antwort, die du gepostet hast, aber wenn ich deinen Code ausführe, erhalte ich die folgende Fehlermeldung: FEHLER: Schema "Daten" existiert nicht
user2867432
user2867432 Sie müssen den Schemanamen ändern, den Sie entsprechend verwenden (z. B. public)
mehmet
Hallo Mehmet, danke für die Lösung, es ist perfekt, aber das funktioniert nur, wenn der Postgres-DB-Benutzer Superuser ist. Gibt es eine Möglichkeit, es ohne Superuser zum Laufen zu bringen?
Geeme
Geeme: lesen „Sicherheit definer“ hier , aber ich habe es selbst nicht verwendet.
Mehmet
Schöne Antwort! Ich werde jedoch in meinem Code nicht zu allgemein sein, um die Lesbarkeit für andere zu gewährleisten.
Manohar Reddy Poreddy
19

Wie Paul erwähnte, funktioniert der Import in pgAdmin:

Rechtsklick auf Tabelle -> Importieren

Wählen Sie die lokale Datei, das Format und die Codierung aus

hier ist ein deutscher pgAdmin GUI Screenshot:

pgAdmin-Import-GUI

Ähnliches können Sie mit DbVisualizer tun (ich habe eine Lizenz, bin mir nicht sicher über die kostenlose Version)

Rechtsklick auf eine Tabelle -> Tabellendaten importieren ...

DbVisualizer-Import-GUI

Andreas L.
quelle
2
DBVisualizer brauchte 50 Sekunden, um 1400 Zeilen mit drei Feldern zu importieren - und ich musste alles von einem String auf das zurücksetzen, was es sein sollte.
Noumenon
19
COPY table_name FROM 'path/to/data.csv' DELIMITER ',' CSV HEADER;
timxor
quelle
10
  1. Erstellen Sie zuerst eine Tabelle

  2. Verwenden Sie dann den Befehl copy, um die Tabellendetails zu kopieren:

Kopieren Sie den Tabellennamen (C1, C2, C3 ....)
von 'Pfad zu Ihrer CSV-Datei' Trennzeichen ',' CSV-Header;

Vielen Dank

user9130085
quelle
3
Wie ist das nicht die akzeptierte Antwort? Warum sollte ich ein Python-Skript schreiben, wenn die Datenbank bereits einen Befehl dazu hat?
Wes
8

Persönliche Erfahrung mit PostgreSQL, immer noch auf einen schnelleren Weg wartend.

1. Erstellen Sie zuerst ein Tabellenskelett, wenn die Datei lokal gespeichert ist:

    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. Wenn sich die Datei \ path \ xxx.csv auf dem Server befindet und postgreSQL nicht über die Berechtigung zum Zugriff auf den Server verfügt, müssen Sie die CSV-Datei über die in pgAdmin integrierte Funktionalität importieren.

Klicken Sie mit der rechten Maustaste auf den Tabellennamen und wählen Sie Importieren.

Geben Sie hier die Bildbeschreibung ein

Wenn Sie immer noch Probleme haben, lesen Sie bitte dieses Tutorial. http://www.postgresqltutorial.com/import-csv-file-into-posgresql-table/

Flowera
quelle
6

Wie importiere ich CSV-Dateidaten in eine PostgreSQL-Tabelle?

Schritte:

  1. Postgresql-Datenbank muss im Terminal verbunden werden

    psql -U postgres -h localhost
  2. Datenbank muss erstellt werden

    create database mydb;
  3. Müssen Benutzer erstellen

    create user siva with password 'mypass';
  4. Mit Datenbank verbinden

    \c mydb;
  5. Müssen Schema erstellen

    create schema trip;
  6. Müssen Tabelle erstellen

    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. Importieren Sie CSV-Dateidaten nach 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. Finden Sie die angegebenen Tabellendaten

    select * from trip.test;
Sivamani
quelle
5

IMHO ist der bequemste Weg, " CSV-Daten in postgresql importieren, den bequemen Weg ;-) " mit csvsql von csvkit , einem über pip installierbaren Python-Paket, zu folgen .

sal
quelle
3
Link Rot ist unersättlich! Der Artikel, auf den Sie verlinkt haben, funktioniert nicht mehr, was mich unbehaglich macht :(
chbrown
Vielleicht möchten Sie erwähnen, dass er py ist.
Bergsteiger
1
Für mich wird ein MemoryError angezeigt, wenn ich versuche, eine große CSV zu importieren, sodass es so aussieht, als würde sie nicht gestreamt.
DavidC
@ DavidC Interessant. Wie groß ist deine Datei? Wie viel Speicher hast du? Wenn es nicht so gestreamt wird, wie es erscheint, empfehle ich, die Daten vor dem Einfügen zu teilen
sal
1
Die Datei war 5 GB groß und ich habe 2 GB Speicher. Ich habe es aufgegeben und am Ende ein Skript verwendet, um die Befehle CREATE TABLE und COPY zu generieren.
DavidC
3

In Python können Sie diesen Code für die automatische Erstellung von PostgreSQL-Tabellen mit Spaltennamen verwenden:

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)

Es ist auch relativ schnell, ich kann mehr als 3,3 Millionen Zeilen in ca. 4 Minuten importieren.

Marc
quelle
2

Sie können auch pgfutter oder noch besser pgcsv verwenden .

pgfutter ist ziemlich fehlerhaft, ich würde pgcsv empfehlen.

So geht's mit pgcsv:

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

Wenn Sie einen einfachen Mechanismus zum Importieren aus Text / Parse Multiline CSV benötigen, können Sie Folgendes verwenden:

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

Lukasz Szozda
quelle
1

Mit DBeaver Community Edition (dbeaver.io) ist es einfach, eine Verbindung zu einer Datenbank herzustellen und anschließend eine CSV-Datei zum Hochladen in eine PostgreSQL-Datenbank zu importieren. Es macht es auch einfach, Abfragen zu stellen, Daten abzurufen und Ergebnismengen in CSV, JSON, SQL oder andere gängige Datenformate herunterzuladen.

Es ist ein plattformübergreifendes Datenbank-Tool von FOSS für SQL-Programmierer, Datenbankadministratoren und Analysten, das alle gängigen Datenbanken unterstützt: MySQL, PostgreSQL, SQLite, Oracle, DB2, SQL Server, Sybase, MS Access, Teradata, Firebird, Hive, Presto usw. Es ist ein brauchbarer FOSS-Konkurrent von TOAD für Postgres, TOAD für SQL Server oder Toad für Oracle.

Ich bin nicht mit DBeaver verbunden. Ich mag den Preis (KOSTENLOS!) Und die volle Funktionalität, aber ich wünschte, sie würden diese DBeaver / Eclipse-Anwendung mehr öffnen und es einfacher machen, DBeaver / Eclipse Analyse-Widgets hinzuzufügen, anstatt dass Benutzer nur für das 199-Dollar-Jahresabonnement bezahlen müssen um Grafiken und Diagramme direkt in der Anwendung zu erstellen. Meine Java-Codierungsfähigkeiten sind verrostet und ich möchte keine Wochen brauchen, um neu zu lernen, wie man Eclipse-Widgets erstellt (nur um festzustellen, dass DBeaver wahrscheinlich die Möglichkeit deaktiviert hat, Widgets von Drittanbietern zur DBeaver Community Edition hinzuzufügen).

Können DBeaver-Hauptbenutzer, die Java-Entwickler sind, einen Einblick in die Schritte zum Erstellen von Analyse-Widgets geben, die der Community Edition von DBeaver hinzugefügt werden sollen?

Rich Lysakowski PhD
quelle
Es wäre schön gewesen zu verstehen, wie man DBeaver tatsächlich zum Importieren einer CSV-Datei verwendet. Auf jeden
Fall
0

Erstellen Sie eine Tabelle und benötigen Sie Spalten, die zum Erstellen einer Tabelle in einer CSV-Datei verwendet werden.

  1. Öffnen Sie Postgres und der rechten Maustaste auf Zieltabelle , die Sie laden möchten und wählen Sie importieren und aktualisieren Sie die folgenden Schritte in Dateioptionen Abschnitt

  2. Durchsuchen Sie nun Ihre Datei unter dem Dateinamen

  3. Wählen Sie CSV im Format

  4. Codierung als ISO_8859_5

Nun gehe zu Misc. Optionen und überprüfen Sie die Kopfzeile und klicken Sie auf Importieren.

Suriruler
quelle
0

Ich habe ein kleines Tool erstellt, das csvDateien super einfach in PostgreSQL importiert , nur einen Befehl, und es erstellt und füllt die Tabellen. Leider verwenden derzeit alle automatisch erstellten Felder den Typ TEXT

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

Das Tool finden Sie unter https://github.com/eduardonunesp/csv2pg

Eduardo Pereira
quelle
Sie haben ein separates Tool für das Äquivalent von psql -h 192.168.99.100 -U postgres mydatabase -c "COPY users FROM 'users.csv' DELIMITER ';' CSV"? Ich denke, der Teil, in dem die Tabelle erstellt wird, ist schön, aber da jedes Feld Text ist, ist es nicht besonders nützlich
GammaGames
1
Ops, danke für die Heads-Ups. Ja, ich habe es geschafft, nun, es hat nur ein paar Stunden gedauert und ich habe coole Sachen in Go und pq und Datenbank-API in Go gelernt.
Eduardo Pereira