8

次のように、複数の .CSV ファイルを postgres データベースにコピーする SQL スクリプトを作成しています。

COPY product(title, department) from 'ys.csv' CSV HEADER;

コピーしたいファイルが複数あります。

COPY product(title, department) from 'ys1.csv' CSV HEADER;
COPY product(title, department) from 'ys2.csv' CSV HEADER;
COPY product(title, department) from 'ys3.csv' CSV HEADER;
COPY product(title, department) from 'ys4.csv' CSV HEADER;
COPY product(title, department) from 'ys5.csv' CSV HEADER;

これには、複数のコピー コマンドの代わりに for ループを使用したいと思います。これは可能ですか?ありがとう

4

6 に答える 6

13

Linux では、リストされているファイルの出力を psql にパイプします。copy標準入力を使用します。

cat /path_to/ys*.csv | psql -c 'COPY product(title, department) from stdin CSV HEADER'

他のOSで同等のものを探す

于 2013-08-30T16:31:25.677 に答える
9

上記の答えを試しましたが、複数のファイルを操作するとエラーが発生しました。2番目のファイルでは、ヘッダーが切り取られていないと思います。

これは私のために働いた:

# get filenames
IMPFILES=(path/FileNamepart.csv)

# import the files
for i in ${IMPFILES[@]}
    do
        psql -U user -d database -c "\copy TABLE_NAME from '$i' DELIMITER ';' CSV HEADER"
        # move the imported file
        mv $i /FilePath
    done

私の場合、インポート後にすべてのファイルを移動します。エラーが発生した場合、どこを見ればよいかがわかります。その場所に新しいファイルが配置されている場合は、スクリプトを再度実行できます。

于 2015-02-04T20:02:42.350 に答える
5

(Postgres > 9.3) キーワードを使用したいがPROGRAM、各 csv ファイルにヘッダーがある場合は、次を使用できますawk

COPY product(title, department) FROM PROGRAM 'awk FNR-1 ys*.csv | cat' DELIMITER ',' CSV;
于 2019-12-05T15:07:10.113 に答える
2

pg_ls_dir を使用してファイル名をループできます。

DO $$

DECLARE file_path TEXT; -- Path where your CSV files are
DECLARE fn_i TEXT; -- Variable to hold name of current CSV file being inserted
DECLARE mytable TEXT; -- Variable to hold name of table to insert data into

BEGIN

    file_path := 'C:/Program Files/PostgreSQL/9.6/data/my_csvs/'; -- Declare the path to your CSV files. You probably need to put this in your PostgreSQL file path to avoid permission issues.
    mytable := 'product(title,department)'; -- Declare table to insert data into. You can give columns too since it's just going into an execute statement.

    CREATE TEMP TABLE files AS 
    SELECT file_path || pg_ls_dir AS fn -- get all of the files in the directory, prepending with file path
    FROM pg_ls_dir(file_path);

    LOOP    
        fn_i := (select fn from files limit 1); -- Pick the first file
        raise notice 'fn: %', fn_i;
        EXECUTE 'COPY ' || mytable || ' from ''' || fn_i || ''' with csv header';
        DELETE FROM files WHERE fn = fn_i; -- Delete the file just inserted from the queue
        EXIT  WHEN (SELECT COUNT(*) FROM files) = 0;
     END LOOP;

END $$;
于 2017-10-09T20:32:41.373 に答える