質問: ■質問内容 windowsバッチからPostgreSQLを呼び出してCSVをインポートしようとしています。 そこで問題となる点が数点ありますのでご存じの方がおられれば教えてもらいたいです。 1.バッチファイルからpsqlを実行した際にSQL側でエラーが発生してもバッチ側でエラーレベルが正しく取得できない。 SQLを外部ファイルにしているから問題なのかもしれません。 「-f "%SQLFILE%"」を「-c "select * from ..."」では正しくエラーレベルが取得できます。 2.CSVファイルがダブルコーテーション区切りの場合でCOPYコマンドでテーブルに入れる場合に「""」がnullにならない。 「with NULL ''」を書いても効かない。 そのためテンポラリテーブルに入れてから置換して別テーブルに入れています。 環境はwindows、PostgreSQL11を使用しています。 【bat】 @echo off setlocal enabledelayedexpansion set CSVFILE=C:\work\import_csv\import_test.csv set SQLFILE=C:\work\import_sql\import_test.sql (psql -h localhost -p 5432 -U postgres -d mydb -f "%SQLFILE%" -v CSV_PATH="%CSVFILE%") echo %errorlevel% endlocal pause 【SQL】 -- テンポラリテーブル作成 create temp table temp_table1 (col1 text ,col2 text ,col3 text, col4 timestamp without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL); -- CSVをテンポラリテーブルにimport COPY temp_table1 (col1, col2, col3) FROM :'CSV_PATH' with encoding 'SJIS' csv HEADER ; -- テンポラリテーブルからselectInsert(空文字をnullに変換) insert into table1 select nullif(col1, ''), nullif(col2, ''), nullif(col3, ''), col4 from temp_table1; 【CSV】 "カラム1","カラム2","カラム3" "0001","あ","え" "0002","","" "0003","い","" 【table1】 CREATE TABLE table1 ( col1 text, col2 text, col3 text, col4 timestamp without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL );
回答: 一点目のpsqlのエラーコードについてですが、 psqlは途中のSQLでエラーが発生しても、致命的なエラーでない場合は最後まで実行します。 その結果、エラーコードとしては正常(0)が返ります。 途中のエラーで処理をとめて、エラーを検知したい場合は`ON_ERROR_STOP`を`on`にします。 SQLのファイルの先頭に`\set ON_ERROR_STOP on`を書くか、 psqlの実行時に`psql -v ON_ERROR_STOP=on -f ....`のどちらかです。 マニュアル: 二点目のCSVの""をNULLで取り込む方法ですが、マニュアルにある`FORCE_NULL`が使えそうですが、どうでしょう。(未確認)