web-dev-qa-db-ja.com

ヘッダー付きのcsvファイルからPostgreSQLにテーブルを自動的に作成できますか?

OS X 10.6.8でPostgreSQL 9.2.6を実行しています。列ヘッダー付きのCSVファイルからデータベースにデータをインポートしたいと思います。これを行うには、COPYステートメントを使用しますが、CSVファイルの各列に対応する列を含むテーブルを最初に手動で作成した場合のみです。 CSVファイルのヘッダーに基づいてこのテーブルを自動的に作成する方法はありますか?

この質問 試した

_COPY test FROM '/path/to/test.csv' CSV HEADER;_

しかし、私はこのエラーを受け取ります:

_ERROR: relation "test" does not exist_

そして、最初に列のないテーブルを作成した場合:

CREATE TABLE test ();

私は得る:

_ERROR: extra data after last expected column_

PostgreSQLに何も見つかりません COPY documentation テーブルの自動作成について。ヘッダー付きのCSVファイルからテーブルを自動的に作成する他の方法はありますか?

43
ihough

COPYcannotがテーブルを作成するため、 COPY ドキュメントには何も見つかりません。
それをCOPYする前に行う必要があります。

24

CsvファイルからPostgresにテーブルをインポートする非常に優れたツールがあります。これはpgfutterと呼ばれるコマンドラインツールです( Windows、Linuxなどのバイナリを使用 )。その大きな利点の1つは、属性/列名も認識することです。

ツールの使用方法は簡単です。たとえば、myCSVfile.csvをインポートする場合:

pgfutter --db "myDatabase" --port "5432" --user "postgres" --pw "mySecretPassword" csv myCSVfile.csv

これにより、csvファイルのヘッダーから取得した列名を持つテーブル(myCSVfileと呼ばれる)が作成されます。さらに、データ型は既存のデータから識別されます。

いくつかの注意:コマンドpgfutterは、使用するバイナリによって異なります。 pgfutter_windows_AMD64.exe(このコマンドを頻繁に使用する場合は名前を変更してください)の場合があります。上記のコマンドはコマンドラインウィンドウで実行する必要があります(たとえば、Windowsではcmdを実行し、pgfutterにアクセスできることを確認します)。別のテーブル名にしたい場合は、--table "myTable";を追加します。特定のデータベーススキーマを選択するには、--schema "mySchema"を使用します。外部データベースにアクセスする場合は、--Host "myHostDomain"を使用します。

pgfuttermyFileにインポートするmyTableのより複雑な例は次のとおりです。

pgfutter --Host "localhost" --port "5432" --db "myDB" --schema "public" --table "myTable" --user "postgres" --pw "myPwd" csv myFile.csv

ほとんどの場合、インポート後にいくつかのデータ型を(テキストから数値に)変更します。

alter table myTable
  alter column myColumn type numeric
    using (trim(myColumn)::numeric)
33
Wolfi

2番目のアプローチがありますが、これは here (mmattから)です。基本的に、Postgres内で関数を呼び出します(最後の引数は列の数を指定します)。

select load_csv_file('myTable','C:/MyPath/MyFile.csv',24)

これがmmattの関数コードです。公開スキーマに取り組んでいるので、少し変更する必要がありました。 (コピーしてPgAdmin SQL Editorに貼り付けて実行し、関数を作成します)

CREATE OR REPLACE FUNCTION load_csv_file(
    target_table text,
    csv_path text,
    col_count integer)
  RETURNS void AS
$BODY$

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
    set schema 'public';

    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;

$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION load_csv_file(text, text, integer)
  OWNER TO postgres;

注:エンコードに関連するテキストファイルのインポートには一般的な問題があります。 csvファイルはUTF-8形式である必要があります。ただし、エンコードを実行しようとするプログラムでは、これが完全に達成されない場合があります。 Notepad ++でファイルを開き、ANSIに変換してUTF8に戻すことで、この問題を克服しました。

15
Wolfi

私はこの手順でそれを達成しました:

  1. Csvファイルをutf8に変換します
    iconv -f ISO-8859-1 -t UTF-8 file.txt -o file.csv
  1. このpythonスクリプトを使用して、テーブルを作成してコピーするSQLを作成します。
#!/usr/bin/env python3
import csv, os
#pip install python-slugify
from slugify import slugify

origem = 'file.csv'
destino = 'file.sql'
arquivo = os.path.abspath(origem)

d = open(destino,'w')
with open(origem,'r') as f:

    header = f.readline().split(';')
    head_cells = []
    for cell in header:
        value = slugify(cell,separator="_")
        if value in head_cells:
            value = value+'_2'
        head_cells.append(value)
    #cabecalho = "{}\n".format(';'.join(campos))

    #print(cabecalho)
    fields= []
    for cell in head_cells:
        fields.append(" {} text".format(cell))
    table = origem.split('.')[0]
    sql = "create table {} ( \n {} \n);".format(origem.split('.')[0],",\n".join(fields))
    sql += "\n COPY {} FROM '{}' DELIMITER ';' CSV HEADER;".format(table,arquivo)

    print(sql)
    d.write(sql)

3.スクリプトを実行します

python3 importar.py

オプション:sqlスクリプトを編集してフィールドタイプを調整します(デフォルトではすべてテキストです)

  1. Sqlスクリプトを実行します。コンソールの略
Sudo -H -u postgres bash -c "psql mydatabase < file.sql" 
0

1つのテーブルについて、Webで見つかる多くの優れたコンバーターの1つを使用して、非常に簡単かつ迅速にオンラインでやりました。 google csvをオンラインでsqlに変換する のいずれかを選択します。

0
Franco