- データベース
psql コマンド 一覧|メタコマンドと起動オプションを実行結果で解説
psqlとは、PostgreSQLに接続してSQLを実行するための公式のコマンドラインツールで、\dtや\copyのような「\(バックスラッシュ)で始まるメタコマンド」でテーブル一覧の表示やCSVの入出力ができます。 SQLはサーバーで実行されますが、メタコマンドはpsql自身が処理するため、覚えておくとデータベースの中身を素早く確認できます。
この記事では、psqlの起動オプションとメタコマンドを「やりたいこと」別の一覧表にまとめ、PostgreSQL 16.13で実際に実行した出力を載せました。~/.psqlrcの実用設定、\copyとCOPYの違い(権限エラーの実例つき)、スクリプト実行時のON_ERROR_STOPの効果、Peer authentication failedやrole does not existなどの接続エラーの再現と対処、MySQLのmysqlコマンドとの対応表まで扱います。
psqlコマンドの早見表
接続・起動オプション
| やりたいこと | コマンド |
|---|---|
| ホスト・ポート・ユーザー・DBを指定して接続 | psql -h 127.0.0.1 -p 5432 -U app -d appdb |
| 接続URIで接続 | psql "postgresql://app@127.0.0.1:5432/appdb" |
| SQLを1つ実行して終了 | psql -d appdb -c "SELECT count(*) FROM app.tasks" |
| SQLファイルを実行 | psql -d appdb -f setup.sql |
| エラーで止める | psql -v ON_ERROR_STOP=1 -f setup.sql |
| 全体を1トランザクションで | psql -1 -v ON_ERROR_STOP=1 -f setup.sql |
| 変数を渡す | psql -v st=todo -f count.sql(SQL内で:'st') |
| CSVで出力 | psql --csv -c "SELECT ..." > out.csv |
| 値だけ出す(見出し・罫線なし) | psql -At -c "SELECT ..." |
| 区切り文字を変える | psql -At -F $'\t' -c "SELECT ..." |
~/.psqlrcを読まない |
psql -X |
| データベース一覧を出して終了 | psql -l |
メタコマンド(psqlの中で使う)
| やりたいこと | メタコマンド | やりたいこと | メタコマンド |
|---|---|---|---|
| データベース一覧 | \l |
接続先の確認 | \conninfo |
| 別のDBに接続 | \c dbname |
スキーマ一覧 | \dn |
| テーブル一覧 | \dt / \dt app.* |
テーブルの定義 | \d テーブル名 |
| 定義+サイズなど詳細 | \d+ / \dt+ |
ビュー一覧 | \dv |
| インデックス一覧 | \di |
関数一覧 | \df |
| 関数のソース | \sf 関数名 |
関数を編集 | \ef 関数名 |
| ロール一覧 | \du |
テーブルの権限 | \dp テーブル名 |
| 拡張機能の一覧 | \dx |
パスワード変更 | \password |
| 縦に表示 | \x auto / \x on |
1回だけ縦に表示 | SELECT ... \gx |
| 実行時間を表示 | \timing on |
繰り返し実行 | \watch interval=2 count=5 |
| CSVを読み込む・書き出す | \copy |
ファイルのSQLを実行 | \i file.sql |
| 結果をファイルへ | \o file.txt(\oで戻す) |
エディタで編集 | \e |
| 結果を変数に入れる | \gset |
条件分岐 | \if \elif \else \endif |
| 変数を設定・表示 | \set / \echo :var |
NULLの表示を変える | \pset null '(null)' |
| メタコマンドのヘルプ | \? |
SQL構文のヘルプ | \h CREATE INDEX |
| 終了 | \q |
直前のエラーを詳しく | \errverbose |
まずは\l→\c→\dt→\d テーブル名の4つで「どこに何があるか」を確認するのが基本の流れです。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「psql コマンド 一覧|メタコマンドと起動オプションを実行結果で解説」
検証環境とサンプル
| 項目 | 内容 |
|---|---|
| PostgreSQL / psql | 16.13(Ubuntu 24.04のパッケージ) |
| 接続 | 127.0.0.1:5432、ロールt28、データベースt28(パスワード認証) |
| 最新版 | PostgreSQL 18(2025年9月リリース)。18での変更点は該当箇所で補足 |
出力をそろえるため、ほとんどの例は-X(~/.psqlrcを読まない)を付けて実行しました。サンプルとして、スキーマappに次のテーブル・ビュー・関数を作っています。
CREATE SCHEMA app;
CREATE TABLE app.tasks (
id serial PRIMARY KEY,
title text NOT NULL,
status text NOT NULL DEFAULT 'todo',
due_on date,
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX tasks_status_idx ON app.tasks(status);
INSERT INTO app.tasks(title, status, due_on) VALUES
('備品を発注する','todo','2026-10-01'),
('議事録をまとめる','doing','2026-09-30'),
('在庫を確認する','done','2026-09-25');
CREATE VIEW app.open_tasks AS SELECT id, title, due_on FROM app.tasks WHERE status <> 'done';
CREATE FUNCTION app.count_tasks(p_status text) RETURNS bigint LANGUAGE sql
AS $$ SELECT count(*) FROM app.tasks WHERE status = p_status $$;
接続する(オプション・URI・環境変数・.pgpass)
psql -h 127.0.0.1 -p 5432 -U t28 -d t28
| オプション | 意味 | 省略したとき |
|---|---|---|
-h |
ホスト名 | Unixドメインソケット(Linuxは/var/run/postgresql) |
-p |
ポート | 5432 |
-U |
ロール名(ユーザー) | OSのユーザー名 |
-d |
データベース名 | ロール名と同じ名前 |
-W / -w |
パスワードを必ず聞く/聞かない | 必要なときだけ聞く |
-Uを省略するとOSのユーザー名が使われるため、後述のrole "root" does not existの原因になります。
接続URIで1行にまとめる
psql -X "postgresql://t28@127.0.0.1:5432/t28?sslmode=disable" -c "\conninfo"
You are connected to database "t28" as user "t28" on host "127.0.0.1" at port "5432".
URIの形式はpostgresql://ユーザー:パスワード@ホスト:ポート/DB名?パラメータです。パスワードをURIやコマンドに直接書くと、シェルの履歴やプロセス一覧に残るため、次の.pgpassか環境変数を使います。
環境変数で省略する
PGHOST=127.0.0.1 PGUSER=t28 PGDATABASE=t28 psql -X -Atc "select current_user, current_database()"
t28|t28
| 環境変数 | 対応するオプション |
|---|---|
PGHOST / PGPORT |
-h / -p |
PGUSER / PGDATABASE |
-U / -d |
PGPASSWORD |
パスワード(公式ドキュメントでは.pgpassの利用が推奨) |
PGSSLMODE |
sslmode |
PSQL_PAGER / PAGER |
結果を表示するページャー |
~/.pgpass でパスワード入力を省く
# ~/.pgpass(ホスト:ポート:DB:ユーザー:パスワード。* でワイルドカード)
127.0.0.1:5432:t28:t28:t28pass
権限が600でないと無視されます。 644のまま実行した結果です。
WARNING: password file "/home/.../.pgpass" has group or world access; permissions should be u=rw (0600) or less
psql: error: connection to server at "127.0.0.1", port 5432 failed: fe_sendauth: no password supplied
chmod 600 ~/.pgpass
psql -X -h 127.0.0.1 -U t28 -d t28 -w -c "select 'ok' as r"
r
----
ok
(1 row)
-wは「パスワードを聞かない」オプションで、パスワードが見つからないときは待たずにエラーで終わります。cronやCIのように人が入力できない場面では-wを付けておくと、入力待ちで止まるのを防げます。
データベース・テーブルの中身を確認する
\conninfo と \l:今どこにつながっているか
t28=> \conninfo
You are connected to database "t28" as user "t28" on host "127.0.0.1" at port "5432".
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
t28=> \l t28
List of databases
Name | Owner | Encoding | Locale Provider | Collate | Ctype | ICU Locale | ICU Rules | Access privileges
------+-------+----------+-----------------+---------+---------+------------+-----------+-------------------
t28 | t28 | UTF8 | libc | C.UTF-8 | C.UTF-8 | | |
(1 row)
本番と検証を行き来するときは、作業の前に\conninfoで接続先を確かめる習慣が役立ちます。PostgreSQL 18では\conninfoが表形式になり、表示される情報が増えました。
\dn・\dt・\dv・\di・\df:オブジェクトの一覧
t28=> \dn
List of schemas
Name | Owner
--------+-------------------
app | t28
public | pg_database_owner
t28=> \dt app.*
List of relations
Schema | Name | Type | Owner
--------+-------+-------+-------
app | tasks | table | t28
t28=> \dv app.*
List of relations
Schema | Name | Type | Owner
--------+------------+------+-------
app | open_tasks | view | t28
t28=> \di app.*
List of relations
Schema | Name | Type | Owner | Table
--------+------------------+-------+-------+-------
app | tasks_pkey | index | t28 | tasks
app | tasks_status_idx | index | t28 | tasks
t28=> \df app.*
List of functions
Schema | Name | Result data type | Argument data types | Type
--------+-------------+------------------+---------------------+------
app | count_tasks | bigint | p_status text | func
\dtだけだと検索パス(通常はpublic)のテーブルしか出ません。 実際、この環境で\dtを実行するとDid not find any relations.と表示されました。別スキーマは\dt app.*、全スキーマは\dt *.*で指定します。末尾に+を付けるとサイズなどの詳細が増えます。
t28=> \dt+ app.*
List of relations
Schema | Name | Type | Owner | Persistence | Access method | Size | Description
--------+-------+-------+-------+-------------+---------------+-------+-------------
app | tasks | table | t28 | permanent | heap | 16 kB |
\d テーブル名:列・型・インデックス
t28=> \d app.tasks
Table "app.tasks"
Column | Type | Collation | Nullable | Default
------------+--------------------------+-----------+----------+---------------------------------------
id | integer | | not null | nextval('app.tasks_id_seq'::regclass)
title | text | | not null |
status | text | | not null | 'todo'::text
due_on | date | | |
created_at | timestamp with time zone | | not null | now()
Indexes:
"tasks_pkey" PRIMARY KEY, btree (id)
"tasks_status_idx" btree (status)
\dは列の型・NOT NULL・デフォルト値・インデックス・外部キーまで1画面で確認できるので、テーブル定義を見るときの第一候補です。\d+にするとStorageやDescription(コメント)列が加わります。
\du・\dp・\sf:ロール、権限、関数のソース
t28=> \du t28
List of roles
Role name | Attributes
-----------+------------
t28 |
t28=> \dp app.tasks
Access privileges
Schema | Name | Type | Access privileges | Column privileges | Policies
--------+-------+-------+-------------------+-------------------+----------
app | tasks | table | | |
t28=> \sf app.count_tasks
CREATE OR REPLACE FUNCTION app.count_tasks(p_status text)
RETURNS bigint
LANGUAGE sql
AS $function$ SELECT count(*) FROM app.tasks WHERE status = p_status $function$
\dpのAccess privilegesが空欄なのは、所有者の既定の権限だけで、追加のGRANTがない状態です。GRANT SELECT ON app.tasks TO reader;を実行すると、reader=r/t28のように表示されます(rはSELECT、aはINSERT、wはUPDATE、dはDELETE)。
結果を見やすくする(\x・\timing・\pset)
\x auto:横に長い結果を縦に表示
t28=> \x on
Expanded display is on.
t28=> SELECT * FROM app.tasks WHERE id = 1;
-[ RECORD 1 ]-----------------------------
id | 1
title | 備品を発注する
status | todo
due_on | 2026-10-01
created_at | 2026-09-29 05:53:06.481446+00
\x autoにすると、画面の幅に収まるときは横、収まらないときだけ縦に自動で切り替わります。 1回だけ縦にしたいときは、;の代わりに\gxで実行します。
t28=> SELECT id, title FROM app.tasks WHERE id = 2 \gx
-[ RECORD 1 ]-----------
id | 2
title | 議事録をまとめる
\timing:実行時間を測る
t28=> \timing on
Timing is on.
t28=> SELECT count(*) FROM generate_series(1, 1000000);
count
---------
1000000
(1 row)
Time: 353.351 ms
時間にはネットワークの往復も含まれます。 サーバー内の処理時間だけを見たいときはEXPLAIN ANALYZEを使います。
\pset:NULLの見え方や出力形式
| 設定 | 効果 |
|---|---|
\pset null '(null)' |
NULLを(null)と表示(空文字と区別できる) |
\pset format csv |
以降の結果をCSVで表示 |
\pset border 2 |
外枠付きの罫線 |
\pset pager off |
ページャー(less)を使わない |
CSVの書き出しと読み込み(\copy と COPY の違い)
\copy で書き出す
psql -X -h 127.0.0.1 -U t28 -d t28 \
-c "\copy (SELECT id, title, status, due_on FROM app.tasks ORDER BY id) TO 'tasks.csv' WITH (FORMAT csv, HEADER)"
cat tasks.csv
COPY 3
id,title,status,due_on
1,備品を発注する,todo,2026-10-01
2,議事録をまとめる,doing,2026-09-30
3,在庫を確認する,done,2026-09-25
SQLのCOPYで同じことをすると
psql -X -h 127.0.0.1 -U t28 -d t28 -c "COPY app.tasks TO '/tmp/t28_tasks.csv' WITH (FORMAT csv)"
ERROR: permission denied to COPY to a file
DETAIL: Only roles with privileges of the "pg_write_server_files" role may COPY to a file.
HINT: Anyone can COPY to stdout or from stdin. psql's \copy command also works for anyone.
COPY ... TO 'ファイル'は「データベースサーバー上のファイル」をサーバーのOSユーザー(postgres)が読み書きするため、スーパーユーザーかpg_write_server_files(読み込みはpg_read_server_files)の権限が必要です。 \copyはpsqlを動かしている手元のPCのファイルを使い、データはSTDIN/STDOUT経由で送られるので、一般ユーザーでも使えます。
| 比較 | \copy(psqlのメタコマンド) |
COPY(SQL) |
|---|---|---|
| ファイルの場所 | psqlを実行しているマシン | データベースサーバー |
| 必要な権限 | テーブルへの通常の権限 | 上記に加えてpg_read_server_files / pg_write_server_filesなど |
| 書き方の制約 | 1行で書く(途中で改行できない) | 通常のSQL |
| 速さ | 大量データでは通信の分だけ差が出ることがある | サーバー内で完結 |
| 向いている場面 | 手元のCSVを入れる・出す | サーバー上のファイルを一括処理 |
\copy で読み込む(列を指定)
printf 'title,status,due_on\n棚卸しをする,todo,2026-10-05\n鍵を返却する,todo,\n' > new_tasks.csv
psql -X -h 127.0.0.1 -U t28 -d t28 \
-c "\copy app.tasks(title, status, due_on) FROM 'new_tasks.csv' WITH (FORMAT csv, HEADER)"
COPY 2
CSVの列とテーブルの列の順番が違うときは、app.tasks(title, status, due_on)のように列を指定します。 CSV形式では空欄(鍵を返却する,todo,の最後)がNULLとして読み込まれます。
結果をCSVやシェル変数で受け取る(--csv・-A・-t)
psql -X -h 127.0.0.1 -U t28 -d t28 --csv -c "SELECT id, title, status FROM app.tasks ORDER BY id"
id,title,status
1,備品を発注する,todo
2,議事録をまとめる,doing
3,在庫を確認する,done
4,棚卸しをする,todo
5,鍵を返却する,todo
psql -X -h 127.0.0.1 -U t28 -d t28 -A -t -c "SELECT id, title FROM app.tasks ORDER BY id"
psql -X -h 127.0.0.1 -U t28 -d t28 -At -F $'\t' -c "SELECT id, status FROM app.tasks ORDER BY id LIMIT 2"
1|備品を発注する
2|議事録をまとめる
3|在庫を確認する
4|棚卸しをする
5|鍵を返却する
1 todo
2 doing
-Aは罫線なし、-tは見出しと件数表示なしです。シェルでcount=$(psql -At -c "SELECT count(*) FROM app.tasks")とすれば、数値だけを変数に入れられます。値にカンマや改行を含む可能性があるなら、--csvのほうが安全です(CSVの規則どおり引用符で囲まれます)。
SQLファイルを実行する(-f・\i・ON_ERROR_STOP)
ON_ERROR_STOP なし・ありの違い
途中の文でエラーになるスクリプトを用意しました。
-- deploy.sql
CREATE TABLE app.labels (id int PRIMARY KEY, name text);
INSERT INTO app.labels VALUES (1, '重要');
INSERT INTO app.labels VALUES (1, '重複'); -- 主キー重複でエラー
INSERT INTO app.labels VALUES (2, '後で');
# ① そのまま実行
psql -X -h 127.0.0.1 -U t28 -d t28 -f deploy.sql; echo "exit=$?"
CREATE TABLE
INSERT 0 1
psql:deploy.sql:3: ERROR: duplicate key value violates unique constraint "labels_pkey"
DETAIL: Key (id)=(1) already exists.
INSERT 0 1
exit=0
既定ではエラーの後も次の文を実行し続け、終了コードは0になります。 4行目の(2, '後で')も登録されていました。
# ② ON_ERROR_STOP を付ける
psql -X -h 127.0.0.1 -U t28 -d t28 -v ON_ERROR_STOP=1 -f deploy.sql; echo "exit=$?"
CREATE TABLE
INSERT 0 1
psql:deploy.sql:3: ERROR: duplicate key value violates unique constraint "labels_pkey"
DETAIL: Key (id)=(1) already exists.
exit=3
エラーの時点で止まり、終了コードが3になります。 ただし、1〜2行目は確定済みなので(1, '重要')は残ります。
# ③ ON_ERROR_STOP と -1(全体を1トランザクション)
psql -X -h 127.0.0.1 -U t28 -d t28 -v ON_ERROR_STOP=1 -1 -f deploy.sql; echo "exit=$?"
psql -X -h 127.0.0.1 -U t28 -d t28 -c "SELECT * FROM app.labels"
exit=3
ERROR: relation "app.labels" does not exist
③ではテーブル作成も含めてすべて取り消されました。 マイグレーションやデータ投入のスクリプトは、③の組み合わせで実行すると「途中まで反映された状態」を防げます。
| 実行方法 | エラー後の動き | 終了コード | 反映 |
|---|---|---|---|
-fのみ |
続行 | 0 | エラー以外は反映 |
-v ON_ERROR_STOP=1 |
停止 | 3 | エラー前まで反映 |
-v ON_ERROR_STOP=1 -1 |
停止 | 3 | 何も反映しない |
psqlの中で別ファイルを読むときは\i count.sql(今いるファイルからの相対パスなら\ir)を使います。
変数と条件分岐(-v・\set・\gset・\if)
-v で値を渡し :'変数' で使う
-- count.sql
SELECT count(*) AS cnt FROM app.tasks WHERE status = :'st';
psql -X -h 127.0.0.1 -U t28 -d t28 -v st=todo -f count.sql
cnt
-----
3
(1 row)
:'st'は値を文字列リテラルとして安全に引用し、:"st"は識別子(列名・テーブル名)として引用、:stはそのまま埋め込みます。 なお、-cで渡したSQLには変数が展開されません。
psql -X -h 127.0.0.1 -U t28 -d t28 -v st=todo -c "SELECT :'st' AS v"
ERROR: syntax error at or near ":"
LINE 1: SELECT :'st' AS v
^
同じSQLをecho "SELECT :'st' AS v;" | psql -v st=todo ...のように標準入力から渡すと、todoと表示されました。
\gset で結果を変数に入れ、\if で分岐
t28=> SELECT count(*) AS n FROM app.tasks \gset
t28=> \echo タスク件数は :n 件です
タスク件数は 3 件です
(この例は、前述の\copyで2件を追加する前に実行したため3件です。)
\ifは比較式を評価しない点に注意します。
t28=> \if :n > 2
unrecognized value "3 > 2" for "\if expression": Boolean expected
比較はSQL側で行い、真偽値を\gsetで受け取ってから\ifに渡します。
SELECT count(*) > 2 AS many FROM app.tasks \gset
\if :many
\echo 3件以上あります
\else
\echo 2件以下です
\endif
3件以上あります
同じSQLを繰り返し実行する(\watch)
printf "SELECT count(*) AS n FROM app.tasks\n\\\\watch interval=1 count=2\n" | psql -X -h 127.0.0.1 -U t28 -d t28
Tue Sep 29 14:53:46 2026 (every 1s)
n
---
5
(1 row)
Tue Sep 29 14:53:47 2026 (every 1s)
n
---
5
(1 row)
\watchは直前のクエリ(クエリバッファ)を繰り返します。 対話中ならSELECT ...を実行した後に\watch 2と入力し、Ctrl+Cで止めます。count=で回数を指定する書き方はPostgreSQL 16から使えます。-c "SELECT ..." -c "\watch ..."と別々の-cで渡すと、\watch cannot be used with an empty queryになりました。
結果をファイルに保存する(\o)・エディタで書く(\e)
\o out.txt
SELECT id, title FROM app.tasks ORDER BY id LIMIT 2;
\o
\echo 画面に戻りました
\o ファイル名以降の結果はファイルへ、引数なしの\oで画面に戻ります。 \eは直前のクエリを環境変数EDITOR(またはPSQL_EDITOR)のエディタで開き、保存して閉じると実行します。長いSQLを直すときに便利です(対話操作のため本記事では未実行)。\passwordも対話入力が必要なため未実行ですが、ALTER ROLE ... PASSWORD '...'と違い、平文のパスワードがログや履歴に残りにくいのが利点です。
~/.psqlrc の実用設定例
psqlは起動時に~/.psqlrcを読み込みます(-Xで無効化)。
-- ~/.psqlrc
\set QUIET 1
\pset null '(null)'
\x auto
\set ON_ERROR_ROLLBACK interactive
\set HISTCONTROL ignoredups
\set HISTSIZE 5000
\set COMP_KEYWORD_CASE upper
\set PROMPT1 '%n@%/%R%# '
\timing on
\set active 'SELECT pid, usename, state, now() - query_start AS elapsed, left(query, 40) AS query FROM pg_stat_activity WHERE state <> ''idle'' ORDER BY elapsed DESC;'
\unset QUIET
-- 上の設定で SELECT NULL AS due_on; と :active を実行した結果
due_on
--------
(null)
(1 row)
Time: 0.232 ms
pid | usename | state | elapsed | query
------+---------+--------+----------+------------------------------------------
7846 | t28 | active | 00:00:00 | SELECT pid, usename, state, now() - quer
(1 row)
Time: 2.279 ms
| 設定 | 効果 |
|---|---|
\set QUIET 1 … \unset QUIET |
起動時の設定メッセージを表示しない |
ON_ERROR_ROLLBACK interactive |
対話中はトランザクション内でエラーが出ても、それまでの操作を失わない |
COMP_KEYWORD_CASE upper |
Tab補完でSQLキーワードを大文字にする |
PROMPT1 '%n@%/%R%# ' |
プロンプトを「ユーザー@DB名」に |
\set active '...' |
よく使うSQLを:activeで呼び出す |
ON_ERROR_ROLLBACKのinteractiveは対話時だけ有効なので、スクリプト実行時の動きは変わりません。スクリプトやCIでは-Xを付けて.psqlrcの影響を受けないようにすると、環境による差が出にくくなります。
よくある接続エラーと対処
実際にエラーを出して確認しました。
| エラーメッセージ | 原因 | 対処 |
|---|---|---|
FATAL: role "root" does not exist |
-U省略でOSユーザー名(root)が使われた |
-Uでロールを指定。またはsudo -u postgres psql |
FATAL: Peer authentication failed for user "t28" |
ソケット接続がpeer認証(OSユーザー名とロール名が一致する必要) |
-h 127.0.0.1でTCP接続(パスワード認証)にする、またはpg_hba.confを見直す |
Connection refused / Is the server running on that host and accepting TCP/IP connections? |
指定したホスト・ポートでサーバーが待ち受けていない | サーバーの起動、-pのポート、listen_addressesを確認 |
No such file or directory / Is the server running locally and accepting connections on that socket? |
ソケットファイルがない(停止中、ポート違い) | 同上。-hでTCP接続も試す |
FATAL: password authentication failed for user "t28" |
パスワード違い | .pgpassやPGPASSWORDの値を確認 |
FATAL: database "t28x" does not exist |
DB名の誤り(-d省略時はロール名と同じDBを探す) |
psql -lで名前を確認し-dで指定 |
fe_sendauth: no password supplied |
-w指定でパスワードが見つからない |
.pgpassの内容と権限600を確認 |
実際の出力の一部です。
$ psql -X -c "select 1" # root ユーザーで -U を省略
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: role "root" does not exist
$ psql -X -U t28 -d t28 -c "select 1" # ソケット接続(pg_hba.conf が peer)
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: Peer authentication failed for user "t28"
$ psql -X -h 127.0.0.1 -p 7289 -U t28 -d t28 -c "select 1" # 誰も待ち受けていないポート
psql: error: connection to server at "127.0.0.1", port 7289 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections?
「socket」と出たらUnixドメインソケット、「at "127.0.0.1"」と出たらTCPで接続しようとしています。 pg_hba.confはこの2つで別の認証方式を指定できるため、-hの有無で結果が変わります。この検証環境のpg_hba.confは、ソケット(local)がpeer、127.0.0.1(host)がscram-sha-256でした。なお、パスワード違いのエラーはSSLありとなしの2回の接続を試すため、同じ行が2回表示されました。
mysqlコマンドとの対応表
MySQLに慣れている人向けに、よく使う操作を対応させました(mysqlは8.0.46で確認)。
| やりたいこと | psql | mysql |
|---|---|---|
| 接続 | psql -h host -p 5432 -U user -d db |
mysql -h host -P 3306 -u user -p db |
| SQLを1つ実行 | -c "SQL" |
-e "SQL" |
| ファイルを実行 | -f file.sql / \i file.sql |
< file.sql / source file.sql |
| DB一覧 | \l |
SHOW DATABASES; |
| DBを切り替え | \c db |
USE db; |
| テーブル一覧 | \dt |
SHOW TABLES; |
| テーブル定義 | \d table |
DESCRIBE table; / SHOW CREATE TABLE table; |
| ユーザー一覧 | \du |
SELECT user, host FROM mysql.user; |
| 接続情報 | \conninfo |
status(\s) |
| 縦表示 | \x / \gx |
末尾を\G |
| 値だけ出す | -A -t |
-B -N(タブ区切り) |
| CSV出力 | --csv / \copy ... TO |
SELECT ... INTO OUTFILE(サーバー側) |
| CSV読み込み | \copy ... FROM |
LOAD DATA LOCAL INFILE |
| 結果をファイルへ | \o file |
tee file |
| パスワードの保存 | ~/.pgpass |
~/.my.cnf / mysql_config_editor |
| 起動時設定 | ~/.psqlrc |
~/.my.cnfの[mysql]セクション |
| エラーで止める | -v ON_ERROR_STOP=1 |
既定で停止(続けるなら--force) |
| ヘルプ | \? / \h |
help |
| 終了 | \q |
exit / \q |
大きな違いは、mysqlのバッチ実行は既定でエラー時に止まり、psqlは止まらない点です。スクリプト実行の手順をMySQLから移すときは、ON_ERROR_STOPを忘れずに付けます。
よくある質問
Q. psqlを終了するには?
A. \qと入力するか、Ctrl+Dを押します。PostgreSQL 11以降はexitやquitでも終了できます。
Q. \dt でテーブルが表示されません。
A. \dtは検索パス(通常はpublicスキーマ)だけを表示します。\dnでスキーマを確認し、\dt スキーマ名.*で指定してください。接続先のDBが違う可能性もあるので、\conninfoも確認します。
Q. 結果が長くて less の画面になり、戻れません。
A. qキーで抜けられます。ページャーを使わないなら\pset pager off、または環境変数PSQL_PAGERで好みのページャーを指定します。
Q. psqlのバージョンとサーバーのバージョンが違っても使えますか?
A. 使えますが、psqlがサーバーより古いと一部のメタコマンドが正しく動かないことがあります。psql --versionとSELECT version();で確認し、psqlはサーバーと同じか新しいバージョンにそろえると安心です。
まとめ
- psqlのメタコマンドは
\で始まり、psql自身が処理する。まず\l→\c→\dt→\dで中身を確認 - 接続は
-h -p -U -dか接続URI。パスワードは権限600の~/.pgpassに置く \dtは検索パスのスキーマだけ。別スキーマは\dt app.*\copyは手元のファイル、COPYはサーバーのファイル。COPYはpg_write_server_filesなどの権限が必要- スクリプトは
-X -v ON_ERROR_STOP=1 -1 -fで実行すると、途中で止まり全体が取り消される \ifは比較式を評価しない。SQLで真偽値を作って\gsetで受け取る- 接続エラーは「socketかTCPか」と
pg_hba.confの認証方式を見ると原因を絞れる
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「psql コマンド 一覧|メタコマンドと起動オプションを実行結果で解説」
株式会社RJCでは、日々の開発で使うコマンドの便利な使い方を、プロジェクトの中で仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。