web-dev-qa-db-ja.com

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

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

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

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

72

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

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

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

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)

if_existsパラメーターは、既存のテーブルを置換または追加するように設定できます。 df.to_sql('pandas_db', engine, if_exists='replace')。これは、追加の入力ファイルタイプ、docs here および here でも機能します。

21
joelostblom

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

ノートのpgドキュメント say

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

したがって、psqlまたは任意のクライアントをローカルサーバーでも使用すると、問題が発生します。そして、他のユーザーに対してCOPYコマンドを表現する場合、たとえばGithubのREADMEでは、リーダーに問題が発生します...

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

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

as ここに記憶

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

私は問題なくこの機能をしばらく使用しています。あなただけの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;
3
mehmet

d6tstack を使用できます。これは、テーブルを作成し、 pd.to_sql() よりも高速です。ネイティブDBインポートコマンド。 PostgresとMYS​​QLおよび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')

また、複数のCSVをインポートし、データスキーマの変更を解決したり、dbに書き込む前にpandas(日付など)で前処理したりする場合にも便利です。 examplesノートブックを参照

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