it-swarm.com.de

Wie kopiere ich aus einer CSV-Datei in eine PostgreSQL-Tabelle mit Kopfzeilen in einer CSV-Datei?

Ich möchte eine CSV-Datei in eine Postgres-Tabelle kopieren. Es gibt ungefähr 100 Spalten in dieser Tabelle, daher möchte ich sie nicht umschreiben, wenn ich nicht muss.

Ich verwende den Befehl \copy table from 'table.csv' delimiter ',' csv;, aber ohne eine erstellte Tabelle bekomme ich ERROR: relation "table" does not exist. Wenn ich eine leere Tabelle hinzufüge, erhalte ich keine Fehlermeldung, aber es passiert nichts. Ich habe diesen Befehl zwei oder dreimal ausprobiert und es gab keine Ausgaben oder Meldungen, aber die Tabelle wurde nicht aktualisiert, als ich sie mit PGAdmin überprüfte. 

Gibt es eine Möglichkeit, eine Tabelle mit den darin enthaltenen Kopfzeilen zu importieren, so wie ich es versuche?

60

Das hat funktioniert. Die erste Zeile hatte Spaltennamen.

COPY wheat FROM 'wheat_crop_data.csv' DELIMITER ';' CSV HEADER
90
G. Cito

Mit der Python library pandas können Sie auf einfache Weise Spaltennamen erstellen und Datentypen aus einer CSV-Datei ableiten.

from sqlalchemy import create_engine
import pandas as pd

engine = create_engine('postgresql://user:[email protected]/db_name')
df = pd.read_csv('/path/to/csv_file')
df.to_sql('pandas_db', engine)

Der Parameter if_exists Kann so eingestellt werden, dass er eine vorhandene Tabelle ersetzt oder an diese angehängt wird, z. df.to_sql('pandas_db', engine, if_exists='replace'). Dies funktioniert auch für zusätzliche Eingabedateitypen, docs hier und hier .

21
joelostblom

Alternativ per Terminal ohne Erlaubnis

Die pg-Dokumentation unter NOTES .__

Der Pfad wird relativ zum Arbeitsverzeichnis des Serverprozesses (normalerweise das Datenverzeichnis des Clusters) und nicht zum Arbeitsverzeichnis des Clients interpretiert.

In der Regel haben Sie mit psql oder einem beliebigen Client, sogar auf einem lokalen Server, Probleme. Bei einer Github-Readme wird der Leser Probleme haben ...

Die einzige Möglichkeit, relative Pfad mit Clientberechtigungen auszudrücken, ist STDIN

Wenn STDIN oder STDOUT angegeben ist, werden Daten über die Verbindung zwischen dem Client und dem Server übertragen.

wie hier erinnert :

psql -h remotehost -d remote_mydb -U myuser -c \
   "copy mytable (column1, column2) from STDIN with delimiter as ','" \
   < ./relative_path/file.csv
8
Peter Krauss

Ich benutze diese Funktion seit einiger Zeit ohne Probleme. Sie müssen nur die Anzahl der Spalten angeben, die sich in der CSV-Datei befinden. Die Kopfzeilennamen werden aus der ersten Zeile übernommen und die Tabelle wird für Sie erstellt:

create or replace function data.load_csv_file
    (
        target_table  text, -- name of the table that will be created
        csv_file_path text,
        col_count     integer
    )

    returns void

as $$

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

begin
    set schema 'data';

    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_file_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 // using quote_ident or %I does not work here!?
    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;
3
mehmet

Sie können d6tstack verwenden, das die Tabelle für Sie erstellt und schneller als pd.to_sql () ist, da native DB-Importbefehle verwendet werden. Es unterstützt Postgres sowie MySQL und MS SQL.

import pandas as pd
df = pd.read_csv('table.csv')
uri_psql = 'postgresql+psycopg2://usr:[email protected]/db'
d6tstack.utils.pd_to_psql(df, uri_psql, 'table')

Es ist auch nützlich, um mehrere CSVs zu importieren, Datenschemaänderungen zu lösen und/oder Vorverarbeitungen mit Pandas durchzuführen (z. B. für Datumsangaben), bevor in db geschrieben wird, siehe weiter unten in Beispielnotizbuch .

d6tstack.combine_csv.CombinerCSV(glob.glob('*.csv'), 
    apply_after_read=apply_fun).to_psql_combine(uri_psql, 'table')
0
citynorman