CSVファイルのヘッダーを含むCSVファイルからPostgreSQLテーブルにコピーする方法


93

CSVファイルをPostgresテーブルにコピーしたい。このテーブルには約100の列があるので、必要がない場合は書き直したくありません。

\copy table from 'table.csv' delimiter ',' csv;コマンドを使用していますが、テーブルを作成せずに取得していERROR: relation "table" does not existます。空白のテーブルを追加してもエラーは発生しませんが、何も起こりません。このコマンドを2、3回試しましたが、出力やメッセージはありませんでしたが、PGAdminで確認したときにテーブルが更新されませんでした。

私がやろうとしているように、ヘッダーが含まれたテーブルをインポートする方法はありますか?


2
テーブルの名前はtable?とても紛らわしい。テーブルは存在しますか、それともCSVに基づいて作成しますか?(できません)
wildplasser 2013

1
まあ、私はそれを別の名前にしましたが、この例ではそれをテーブルと呼びましょう。私はそれが存在する場合も存在しない場合も試しましたが\copy table(column1, column2, ...) from 'table.csv' delimiter ',' csv;、運もありませんでした。理想的には、CSVだけでテーブルを作成し、そのファイルのヘッダーを使用できます。
スタンレーカップフィル


2
大きなcsvをpostgresテーブルに変換することを計画しているすべての人に向かいます-postgresは、1つのテーブルで1600列に制限されています。テーブルを1600列サイズのテーブルに分割してから結合することはできません。データベースを再設計する必要があります。
Achekroud 2015年

Pythonが利用できる場合は、d6tstackを使用できます。スキーマの変更も処理します。
citynorman 2018年

回答:


135

これはうまくいきました。最初の行には列名が含まれていました。

COPY wheat FROM 'wheat_crop_data.csv' DELIMITER ';' CSV HEADER

5
このコマンドの問題は、DBスーパーユーザーでなければならないことだと思います。\ copyも通常のユーザーとして機能します
Exocom

29
COPYテーブルを作成したり、テーブルに列を追加したりするのではなく、既存の列を持つ既存のテーブルに行を追加します。おそらく、質問者は〜100列の作成を自動化したいと考えてCOPYおり、少なくともPG 9.3の時点ではこの機能はありません。
DanielVérité2014

2
@Exocom良いキャッチ。私が使用しているpostgresシステムのDBの管理者またはスーパーユーザーではないので(pgadminを使用すると、使用しているデータベースの所有者になり、限られた権限/役割しか与えられません)、 `\ COPY 'を使用したはずです。乾杯
G. Cito 14

2
@Danielユーザーのテーブルが既に存在し、必要なすべての列があり、単純にデータを求めていることを理解しましたADD
G. Cito 2014

ガットsyntax error at or near "HEADER" LINE 2: delimiter ',' CSV HEADERAWS赤方偏移に。
ミスリル

24

Pythonライブラリをpandas使用すると、列名を簡単に作成し、csvファイルからデータ型を推測できます。

from sqlalchemy import create_engine
import pandas as pd

engine = create_engine('postgresql://user:pass@localhost/db_name')
df = pd.read_csv('/path/to/csv_file')
df.to_sql('pandas_db', engine)

if_existsパラメータは、例えばを交換するか、既存のテーブルに追加するように設定することができますdf.to_sql('pandas_db', engine, if_exists='replace')。これは、追加の入力ファイルタイプでも機能します。ドキュメントはこちらこちらです。


1
pd.DataFrame.from_csvの方が問題が少ないことがわかりますが、この答えはこれを実行する最も簡単な方法です(IMO)。
ブロック

確かに、なぜのpd.read_excel代わりにを入力したのかわかりませんpd.read_csv。答えを更新しました。
joelostblom 2015年

1
これは、大きなcsvを保持するテーブルを事前に作成したくない場合に最適なソリューションです。ただし、前向きです-postgresはテーブルで1600列しか使用できません。どうやら他のDBエンジンはもっと許可するでしょう。このコンセンサスはまだ疫学までフィルタリングされていませんが、これほど多くの列があることは明らかにSQLフォームとしては不十分です。
Achekroud 2015年

1
デフォルトでdf.to_sql()非常に低速ですが、これを高速化するにはd6tstackを使用できます。スキーマの変更も処理します。
citynorman 2018年

13

許可のない端末による代替

NOTESpgドキュメントは 言う

パスは、クライアントの作業ディレクトリではなく、サーバープロセスの作業ディレクトリ(通常はクラスターのデータディレクトリ)に関連して解釈されます。

したがって、psqlローカルサーバーでさえ、または任意のクライアントを使用すると、問題が発生します。Github READMEでは、読者は問題を抱えています...

クライアントの権限で相対パスを表現する唯一の方法は、STDINを使用することです。

STDINまたはSTDOUTが指定されている場合、データはクライアントとサーバー間の接続を介して送信されます。

以下のように、ここで思い出しました

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

3

私はこの機能をしばらく問題なく使用しています。csvファイルにある列の数を指定するだけで、最初の行からヘッダー名が取得され、テーブルが作成されます。

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;

set schema 'data';あなたに
合った

0

テーブルを作成するd6tstackを使用できますこれは、ネイティブDBインポートコマンドを使用するため、pd.to_sql()より高速です。Postgres、MYSQL、MS SQLをサポートしています。

import pandas as pd
df = pd.read_csv('table.csv')
uri_psql = 'postgresql+psycopg2://usr:pwd@localhost/db'
d6tstack.utils.pd_to_psql(df, uri_psql, 'table')

また、複数のCSVのインポート、データスキーマの変更の解決、データベースへの書き込み前のパンダによる前処理(例:日付の場合)にも役立ちます。サンプルノートでさらに下を参照してください。

d6tstack.combine_csv.CombinerCSV(glob.glob('*.csv'), 
    apply_after_read=apply_fun).to_psql_combine(uri_psql, 'table')
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.