※この記事にはアフィリエイト広告(プロモーション)が含まれます。
この記事の出力は PostgreSQL 18.6(Ubuntu 26.04)の psql で採りました。
まず見る(結論)
psql -d mydb -f setup.sql # 実行(エラーがあっても最後まで流れる)
psql -d mydb -v ON_ERROR_STOP=1 -f setup.sql # 最初のエラーで止める(終了コード 3)
psql -d mydb -1 -v ON_ERROR_STOP=1 -f setup.sql # 全体を1トランザクションに(失敗したら全部戻る)
psql -d mydb -c 'SELECT 1' # 1文だけ
mydb=# \i /path/to/setup.sql # psql の中から
バッチやデプロイで使うなら -v ON_ERROR_STOP=1 を付けます。
エラーが出たときの動き
3行目でキー重複になるファイルで比べました。
CREATE TABLE t2 (id int PRIMARY KEY);
INSERT INTO t2 VALUES (1);
INSERT INTO t2 VALUES (1); -- 3行目: duplicate key value violates unique constraint
INSERT INTO t2 VALUES (2);
SELECT count(*) FROM t2;
| オプション | 3行目より後 | 表に残ったもの | 終了コード |
|---|---|---|---|
| なし | 実行される(count は 2) | 1, 2 | 0 |
-v ON_ERROR_STOP=1 |
実行されない | 1 | 3 |
-1 |
current transaction is aborted で全部失敗 |
表ごと無し | 0 |
-1 -v ON_ERROR_STOP=1 |
実行されない | 表ごと無し | 3 |
エラーは psql:/tmp/fsv/err.sql:3: ERROR: ... の形で、ファイル名と行番号を付けて標準エラーに出ます。失敗したら全部戻し、終了コードでも判定したいなら -1 と -v ON_ERROR_STOP=1 を両方付けます。
psql の終了コード
| コード | 実際に出た場面 |
|---|---|
| 0 | 正常終了。ON_ERROR_STOP 無しなら SQL エラーがあっても 0 |
| 1 | -f のファイルが無い(No such file or directory)、-c の文が失敗 |
| 2 | 接続できない(パスワード誤り・サーバー停止・DB が無い) |
| 3 | ON_ERROR_STOP でスクリプトが止まった |
-c で文を渡す
-c 'SELECT 1 AS a; SELECT 2 AS b' と1つにまとめても、-c 'SELECT 1 AS a' -c 'SELECT 2 AS b' と分けても、両方の結果が表示されました。ただし1つの -c に複数の文を書くと、まとめて1トランザクションで実行されます。-c 'CREATE TABLE t3 (id int); INSERT INTO t3 VALUES (1); INSERT INTO t3 VALUES (1/0)' は division by zero で終了コード 1 になり、t3 は作られていませんでした。
\i と \ir の違い
\i の相対パスは psql を起動したディレクトリから、\ir は \ir を書いたファイルのあるディレクトリから探します。sub/main.sql から同じフォルダの child.sql を読む場合で比べました。
| 実行のしかた | \i child.sql |
\ir child.sql |
|---|---|---|
別のディレクトリから psql -f /tmp/fsv/sub/main.sql |
child.sql: No such file or directory |
読める |
cd /tmp/fsv/sub してから psql -f main.sql |
読める | 読める |
ファイルから別のファイルを読み込むなら \ir を使います。\i で読み込みに失敗しても、終了コードは 0 でした。
変数を渡す
-- var.sql
SELECT :'name' AS name, :id AS id;
SELECT * FROM t1 WHERE id = :id;
psql -d mydb -v name=taro -v id=1 -f var.sql
:'name' は単一引用符で囲んだ文字列('taro')、:id はそのまま(1)に置き換わります。-v を付け忘れると syntax error at or near ":" になります。
結果をファイル・CSV に出す
| オプション | 出力 |
|---|---|
-At |
1|a(見出し・罫線・件数なし) |
-At -F ',' |
1,a |
--csv |
id,name と 1,a(見出し付き) |
-o out.txt |
結果をファイルへ。NOTICE やエラーは画面に出る |
-L log.txt |
実行した文と結果をファイルに追記 |
-e / -a |
実行した文を結果の前に表示 |
-q |
CREATE TABLE INSERT 0 1 などの完了メッセージを出さない |
シェルの変数に値を1つだけ取り込むなら -At を使います。CSV の入出力は COPY と \copy の記事に書きました。
ファイルの中身で引っかかる点
- BOM 付き UTF-8・CRLF の改行は、どちらもそのまま実行できた
- 文の終わりのセミコロンを忘れると、次の文とつながって
syntax error at or near "2"(行番号は次の文の行) - ファイル最後の文はセミコロンが無くても実行される
- 標準入力からも流せる(
psql < setup.sqlか-f -)。-f -ではメッセージにpsql:<stdin>:1:と行番号が付き、リダイレクトだけでは付かない
接続オプション
-h ホスト、-p ポート、-U ユーザー、-d データベースです。パスワードは PGPASSWORD か ~/.pgpass で渡します。-X を付けると ~/.psqlrc を読まないので、スクリプトの結果が個人の設定に左右されません。接続できないときは password authentication failed の記事と 外部から接続できないときの記事を見てください。
関連: PostgreSQLでテーブル一覧を表示する / データベース一覧と\c / pg_dumpとpg_restore