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期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?