CSVファイルデータをPostgreSQLテーブルにインポートする方法


601

CSVファイルからデータをインポートしてテーブルに入力するストアドプロシージャを作成するにはどうすればよいですか?


18
なぜストアドプロシージャなのですか?コピーはトリックをします
フランク・ハイケンズ

1
私はcsvファイルをアップロードするユーザーインターフェイスを持っています。これをフックするには、実際にcvsファイルからデータをコピーするストアドプロシージャが必要です
vardhan

3
COPYの使用方法について詳しく教えてください。
バルダン

17
Bozhidar Batsovはすでに例へのリンクを提供しています。すばらしいマニュアルも役立ちます:postgresql.org/docs/8.4/interactive/sql-copy.html
Frank Heikens

回答:


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を使用しても同じトリックが実行されます。root以外のアカウントでCOPYを使用すると、Fedora 16で問題が発生します。
asksw0rder 2012年

81
ヒント:zip_codes(col1、col2、col3)を使用して、CSVにある列を指定できます。列は、ファイルに表示されるのと同じ順序でリストする必要があります。
David Pelaez 2013年

6
@ asksw0rder \ copyには同じ構文がありますか?bcoz \ copyで構文エラーが発生します
JhovaniC

6
ヘッダー行を含める必要がありますか?
bernie2436 2013年

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

222

COPY(dbサーバーで動作する)使用する権限がない場合は、\copy代わりに(dbクライアントで動作する)を使用できます。Bozhidar Batsovと同じ例を使用します。

テーブルを作成します。

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を使用すると、ファイルのアクセス可能性とアクセス権はサーバーではなくクライアントに依存します。

そして注意:

ID列の場合、COPY FROMコマンドは常に、INSERTオプションOVERRIDING SYSTEM VALUEのように、入力データで提供される列の値を書き込みます。


\ copy voters(ZIP、CITY)FROM '/Users/files/Downloads/WOOD.TXT' DELIMITER '、' CSVヘッダー; エラー:予想される最後の列の後の追加データCONTEXT:有権者のコピー、2行目: "OH0012781511,87,26953、HOUSEHOLDER、SHERRY、LEIGH ,, 11/26 / 1965,08 / 19/1988、、211 N GARFIELD ST、、BLOOMD ...」
JZ。

@JZ。同様のエラーが発生しました。余計な空欄があったからです。csvを確認し、空白の列がある場合はそれが原因である可能性があります。
アレックスベネット16

5
これはやや誤解を招く可能性がCOPYあります:との違い\copyは単なるアクセス許可以上のものであり、単に ``を追加して魔法のように機能させることはできません。ここで(エクスポートのコンテキストで)説明を参照してください:stackoverflow.com/a/1517692/157957
IMSoP

@IMSoP:そうです、明確にするためにサーバーとクライアントの言及を追加しました
bjelli

@bjelliは\ copyがcopyより遅いですか?RDSに1.5MBのファイルとdb.m4.largeインスタンスがあり、このコピーコマンドが実行されてから数時間になります(少なくとも3つ)。
セバスチャン

79

これをすばやく行う方法の1つは、Python pandasライブラリを使用することです(バージョン0.15以上が最適です)。これはあなたのために列の作成を処理します-明らかにそれがデータ型に対して行う選択はあなたが望むものではないかもしれませんが。それがあなたの望みどおりにいかない場合は、常にテンプレートとして生成された「テーブルの作成」コードを使用できます。

以下に簡単な例を示します。

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
ユーザー名とパスワード:ログインを作成し、ユーザーにDBを割り当てる必要があります。pgAdminを使用する場合は、GUIを使用して「ログイン/グループの役割」を作成します
Somnath Kadam

9
Pandasは、SQL(vs csvファイル)にロードする非常に遅い方法です。桁違いに遅くなることがあります。
user48956

これはデータを書き込む方法の1つかもしれませんが、バッチ処理と優れた計算能力があっても非常に遅くなります。CSVを使用すると、これを実現できます。
Ankit Singh 2018

df.to_sql()非常に遅いです。d6tstackd6tstack.utils.pd_to_psql()から使用できます。パフォーマンス比較を参照してください
citynorman

30

インポートを実行するためのGUIを提供するpgAdminを使用することもできます。それはこのSOスレッドで示されています。pgAdminを使用する利点は、リモートデータベースでも機能することです。

ただし、以前のソリューションと同様に、データベース上にテーブルが既に存在している必要があります。各人が独自のソリューションを持っていますが、私が通常行うことは、ExcelでCSVを開き、ヘッダーをコピーし、別のワークシートに転置して特別に貼り付け、対応するデータ型を次の列に配置し、それをコピーしてテキストエディターに貼り付けるだけです次のような適切なSQLテーブル作成クエリと一緒に:

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

1
plsは、貼り付けたデータのいくつかのサンプル行を示しています
18

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
こんにちはメフメット、あなたが投稿答えてくれてありがとう私はあなたのコードを実行したとき、私は、次のエラーメッセージが表示されます:ERROR:スキーマ「データ」は存在しません
user2867432

user2867432それに応じて使用するスキーマ名を変更する必要があります(例:public
mehmet

こんにちはメフメット、解決策をありがとう、それは完璧ですが、これはpostgres DBユーザーがスーパーユーザーである場合にのみ機能します。スーパーユーザーなしで機能させる方法はありますか?
Geeme 2017年

Geeme:ここで「セキュリティ定義」を読んでください。しかし、私はそれを自分で使用していません。
メフメット2017年

美しい答え!私は他の人が読みやすいようにコードを一般化しすぎていません。
Manohar Reddy Poreddy

19

Paulが述べたように、インポートはpgAdminで機能します。

テーブルを右クリック->インポート

ローカルファイル、フォーマット、コーディングを選択

これはドイツのpgAdmin GUIスクリーンショットです:

pgAdminインポートGUI

DbVisualizerでできること(私はライセンスを持っていますが、無料版はわかりません)

テーブルを右クリック->テーブルデータのインポート...

DbVisualizerインポートGUI


2
DBVisualizerは、3つのフィールドを持つ1400行をインポートするのに50秒かかりました。そして、文字列から想定されていたものにすべてをキャストし直す必要がありました。
Noumenon

19
COPY table_name FROM 'path/to/data.csv' DELIMITER ',' CSV HEADER;

10
  1. 最初にテーブルを作成する

  2. 次に、copyコマンドを使用してテーブルの詳細をコピーします。

'path to your csv file' delimiter '、' csv header
から table_name(C1、C2、C3 ....)コピーします。

ありがとう


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はサーバーにアクセスする権限を持たないため、pgAdminの組み込み機能を使用して.csvファイルをインポートする必要があります。

テーブル名を右クリックして、インポートを選択します。

ここに画像の説明を入力してください

それでも問題が解決しない場合は、このチュートリアルを参照してください。 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にインポートする、快適な方法;-)に従いcsvkitからcsvsqlを使用することです。これは、pipを介してインストール可能なpythonパッケージです。


3
リンク腐敗は貪欲です!リンクした記事が機能しなくなったため、不快になりました:(
chbrown

あなたは彼がpyであることを言及したいかもしれません。
mountainclimber

1
大きなCSVをインポートしようとすると、ストリーミングされないように見えて、MemoryErrorが発生します。
DavidC、

@DavidC興味深い。ファイルのサイズはどれくらいですか?どのくらいのメモリがありますか?表示されているようにストリーミングされない場合は、挿入前にデータをチャンク化することをお勧めします
sal

1
ファイルのサイズは5GBで、メモリは2GBあります。私はそれをあきらめ、最後にスクリプトを使用して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)

また、比較的高速で、約4分で330万行以上をインポートできます。


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、またはその他の一般的なデータ形式へのダウンロードも簡単になります。

これは、SQLプログラマー、DBA、アナリスト向けのFOSSマルチプラットフォームデータベースツールであり、MySQL、PostgreSQL、SQLite、Oracle、DB2、SQL Server、Sybase、MS Access、Teradata、Firebird、Hive、Prestoなどの一般的なデータベースをすべてサポートしています。 TOAD for Postgres、TOAD for SQL Server、またはToad for Oracleの実行可能なFOSSライバルです。

私はDBeaverとは関係ありません。私は価格(無料)とフル機能が気に入っていますが、ユーザーに年間$ 199のサブスクリプションの料金を支払うだけでなく、このDBeaver / Eclipseアプリケーションをさらに開き、分析ウィジェットをDBeaver / Eclipseに簡単に追加できるようにしたいと思いますアプリケーション内で直接グラフとチャートを作成します。私のJavaコーディングスキルは錆びており、Eclipseウィジェットの構築方法を再学習するのに何週間もかかる気がありません(DBeaverがサードパーティのウィジェットをDBeaver Community Editionに追加する機能をおそらく無効にしていることを確認するためだけです)。

Java開発者であるDBeaverパワーユーザーは、DBeaverのCommunity Editionに追加する分析ウィジェットを作成する手順についての洞察を提供できますか?


DBeaverを実際に使用してCSVファイルをインポートする方法を理解できたら良かったでしょう。とにかく、これは役立つかもしれません:dbeaver.com/docs/wiki/Data-transfer
umbe1987

0

テーブルを作成し、csvファイルでテーブルを作成するために使用する必要な列を用意します。

  1. postgresを開き、ロードするターゲットテーブルを右クリックしてインポートを選択し、ファイルオプションセクションで次の手順を更新します。

  2. 次に、ファイルをファイル名で参照します

  3. 形式でcsvを選択

  4. ISO_8859_5としてエンコード

今後藤その他を。オプションとヘッダーを確認し、インポートをクリックします。


0

csvファイルをPostgreSQLに非常に簡単にインポートする小さなツールを作成しました。コマンドを1つ実行するだけで、残念ながら、自動的に作成されたすべてのフィールドが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
Ops、頭を上げてくれてありがとう。ええ、私はそれを行いました。まあ、それはほんの数時間しかかかりませんでした、そしてGoとpqとGoでのデータベースAPIで素晴らしいものを学びました。
Eduardo Pereira、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.