PostgreSQL コマンドチートシート
PostgreSQL を素早く参照:psql クライアント コマンド、DDL / DML 文、join / 集約、インデックス、トランザクション、バックアップ / リストア — よく使うオプションと実用例をまとめました。
35 コマンド
接続
psql -h <host> -p <port> -U <user> -d <db>リモート / ローカル データベースへ対話 psql セッションを開きます。
-h host; -p 5432(既定); -U user; -d dbname; -W パスワード強制; -f file スクリプト実行; -c 1 コマンド実行
PGPASSWORD=secret psql -h db.example.com -U app -d app_productionpsql -U <user> <db> --variable='ON_ERROR_STOP=1' -f <file.sql>SQL スクリプトをデータベースに対し実行し、最初のエラーで停止します。
psql -U app -d app -v ON_ERROR_STOP=1 -f migrations/0001_init.sqlpsql メタ コマンド
\l[+] \c[onnect] [<db>]データベースを一覧;その後に 1 つに接続します。
\l+ でサイズ / 表領域情報; \c db user で対象を変更
\l+; \c app_dev\dt[+] [<pattern>]現在のスキーマ内でパターンに一致するテーブルを一覧(既定:public)。
\dt+ でサイズ + 説明; \dt *.* ですべてのスキーマ; \d table でテーブル詳細
\dt+ public.*\d <table|view|index|seq|matview>オブジェクト構造を確認:列、インデックス、FK、コメント。
\d orders\dn / \du / \dv / \diそれぞれスキーマ / ロール / ビュー / インデックスを一覧。
\du; \di+ idx_orders_user_id\timing / \x / \? / \qクエリ計測 / 拡張表示の切替、ヘルプ表示、セッション終了。
\timing on; \x auto; SELECT * FROM orders LIMIT 2; \q\copy <table> FROM '<file>' DELIMITER ',' CSV HEADERファイルからデータを一括ロード(サーバ側ですがクライアント FS を使用)。
\copy orders(order_id,user_id,total,created_at) FROM '/tmp/orders.csv' WITH CSV HEADERデータベース / スキーマ
CREATE DATABASE <db>テンプレート データベース設定で新規データベースを作成します。
OWNER role; TEMPLATE template0; ENCODING 'UTF8'; LC_COLLATE
CREATE DATABASE app_dev OWNER app_user ENCODING 'UTF8' TEMPLATE template0DROP DATABASE <db>データベースを削除(使用中でないこと;IF EXISTS + FORCE と併用することが多い)。
DROP DATABASE WITH (FORCE); postgres 13+
DROP DATABASE IF EXISTS app_old;CREATE SCHEMA / DROP SCHEMAテーブル / ビューの名前空間;既定 search_path に含まれます。
CREATE SCHEMA IF NOT EXISTS audit; DROP SCHEMA staging CASCADE;テーブル / DDL
CREATE TABLE新しいテーブルを列 / 型 / 既定値 / 制約付きで定義。
PRIMARY KEY; FOREIGN KEY ... REFERENCES; UNIQUE; CHECK; INHERITS; PARTITION BY RANGE|LIST
CREATE TABLE orders (id bigserial PRIMARY KEY, user_id int NOT NULL REFERENCES users(id), total numeric(10,2) NOT NULL DEFAULT 0, created_at timestamptz NOT NULL DEFAULT now());ALTER TABLE列の追加 / 削除 / リネーム、型変更、制約追加、ストレージ パラメータ設定。
ADD COLUMN; DROP COLUMN; RENAME TO; ADD CONSTRAINT; ALTER COLUMN ... TYPE
ALTER TABLE orders ADD COLUMN currency char(3) NOT NULL DEFAULT 'USD', ADD CONSTRAINT chk_cur CHECK (currency IN ('USD','EUR','CNY'));DROP TABLE / TRUNCATEテーブルを削除(FK から参照されていれば CASCADE);TRUNCATE は高速に空に。
DROP TABLE ... CASCADE; TRUNCATE ... RESTART IDENTITY CASCADE
TRUNCATE TABLE staging.events RESTART IDENTITY CASCADE;COMMENT ON <table|column> IS '...'データベース オブジェクトに注釈を付与 — \d+ と IDE ツールチップに表示されます。
COMMENT ON COLUMN orders.total IS 'Subtotal before tax' DML
INSERT INTO <table> [(cols)] VALUES (...) [RETURNING ...]行を 1 行以上挿入;RETURNING で挿入行の列を取得。
INSERT ... SELECT; ON CONFLICT DO NOTHING / DO UPDATE(upsert); RETURNING
INSERT INTO orders(user_id, total) VALUES (42, 19.95) RETURNING id, created_at;UPDATE ... SET ... [WHERE ...] [RETURNING ...]条件に一致する行を更新;意図的でない限り必ず WHERE で範囲を限定。
UPDATE ... FROM t2 WHERE ...; CTE(WITH ...)+ UPDATE; ... RETURNING
UPDATE orders SET status='paid' WHERE user_id = 42 AND created_at < now() - interval '7 days' RETURNING id;DELETE FROM ... [WHERE ...] [RETURNING ...]条件に一致する行を削除;テーブル全削除は TRUNCATE が高速。
DELETE ... USING t2 WHERE ...; RETURNING
DELETE FROM orders WHERE status='cancelled' AND created_at < now() - interval '30 days' RETURNING id;クエリ / フィルタ
SELECT ... FROM ... WHERE ... ORDER BY ... LIMIT N OFFSET Mフィルタ、ソート、ページネーションを付けて行を読み取り。
WHERE col op ANY/ALL(array); LIMIT n OFFSET n; FETCH FIRST n ROWS ONLY; FOR UPDATE/SHARE ロック
SELECT id, status, total FROM orders WHERE user_id = 42 ORDER BY created_at DESC LIMIT 10 OFFSET 20;DISTINCT / GROUP BY / HAVING重複排除、列で集約、集約結果に対する絞り込み。
GROUP BY ROLLUP(a,b); GROUPING SETS; HAVING 集約後の絞り込み; FILTER (WHERE ...) で NULL を維持
SELECT user_id, count(*) FILTER (WHERE status='paid') AS paid, sum(total) AS gmv FROM orders GROUP BY user_id HAVING count(*) >= 3;結合
[INNER | LEFT | RIGHT | FULL] JOIN ... ON ...複数テーブルの行を組合せ;LEFT JOIN は左側の不一致行を保持。
JOIN LATERAL; NATURAL JOIN; USING(col) を ON の代わりに; CROSS JOIN 直積
SELECT u.email, count(o.id) FROM users u LEFT JOIN orders o ON o.user_id = u.id GROUP BY u.email;WITH cte AS (...) SELECT ...サブクエリを CTE として実体化;再帰 CTE で階層 / グラフを扱います。
WITH RECURSIVE tree AS (SELECT id, parent_id, name FROM cats WHERE parent_id IS NULL UNION ALL SELECT c.id, c.parent_id, c.name FROM cats c JOIN tree t ON c.parent_id = t.id) SELECT * FROM tree;集約
count() / sum() / avg() / min() / max() / array_agg() / string_agg()組み込みの集約関数;FILTER 句や GROUP BY と組合せると強力。
count / sum の中で DISTINCT; array_agg / string_agg 内で ORDER BY
SELECT date_trunc('day', created_at) AS day, sum(total) AS gmv FROM orders GROUP BY day ORDER BY day DESC LIMIT 7;インデックス / ビュー
CREATE INDEX ...WHERE / ORDER BY を高速化;部分インデックスでホット サブセットを狙えます。
CONCURRENTLY(排他ロックなし); INCLUDE (a,b) カバリング; USING btree|gin|gist|hash; 部分 WHERE
CREATE INDEX CONCURRENTLY idx_orders_user_created ON orders(user_id, created_at DESC) INCLUDE (total);EXPLAIN [ANALYZE] <query>クエリ プランを表示;ANALYZE で実行し実時間と行数を報告。
EXPLAIN (ANALYZE, BUFFERS, VERBOSE); FORMAT JSON / TEXT / YAML
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM orders WHERE user_id = 42 ORDER BY created_at DESC LIMIT 10;VACUUM / ANALYZE / REINDEXストレージと統計の保守:不要タプル再利用、プランナ統計更新、インデックス再構築。
VACUUM (FULL) テーブル書換; ANALYZE 統計更新; REINDEX 再構築; 通常は autovacuum が処理
VACUUM (ANALYZE) orders;CREATE VIEW / MATERIALIZED VIEWクエリを保存;マテリアライズド ビューは実際にキャッシュ(リフレッシュ必要)。
CREATE OR REPLACE VIEW; MATERIALIZED VIEW ... WITH NO DATA; REFRESH MATERIALIZED VIEW CONCURRENTLY
CREATE MATERIALIZED VIEW mv_user_orders AS SELECT user_id, count(*) FROM orders GROUP BY user_id; CREATE UNIQUE INDEX ON mv_user_orders(user_id);トランザクション
BEGIN / COMMIT / ROLLBACK複数の文を 1 つのアトミック作業単位に集約(ACID)。
BEGIN ISOLATION LEVEL SERIALIZABLE; COMMIT/ROLLBACK AND CHAIN; SAVEPOINT ラベル
BEGIN ISOLATION LEVEL REPEATABLE READ; UPDATE orders SET ... WHERE ...; ROLLBACK ON ERROR; COMMIT;SELECT ... FOR UPDATE / FOR SHAREトランザクション終了まで該当行をロック;同時更新を防止。
FOR UPDATE / SHARE; キュー向け NOWAIT または SKIP LOCKED
SELECT id FROM jobs WHERE status='queued' ORDER BY id LIMIT 1 FOR UPDATE SKIP LOCKED;バックアップ / リストア
pg_dump <db> -Fc -f <file.dump>データベースをカスタム形式ファイルにダンプ(並列 / 選択的リストア)。
-Fc カスタム; -Ft tar; -Fp プレーン SQL; --schema=; --exclude-table=; -Fd 用 -j jobs
pg_dump -Fc -d app -f /backup/app-$(date +%F).dumppg_restore -d <db> <file.dump>カスタム / tar / dir ダンプから必要なスキーマ / データ / ロールのみリストア。
--clean 先にオブジェクト削除; --if-exists; --schema=; --table=; --jobs=N; --no-owner; --single-transaction
pg_restore -d app_dev --clean --if-exists --jobs=4 /backup/app.dumppsql -d <db> -f <file.sql>プレーン SQL ダンプ(pg_dump -Fp の出力)をリストアします。
psql -U app -d app_new -v ON_ERROR_STOP=1 -f /backup/app.sqlユーザ / 権限
CREATE ROLE / ALTER ROLEロールはログイン(LOGIN)したりオブジェクトを所有可能;属性をロール毎に付与。
LOGIN|REPLICATION|INHERIT|NOSUPERUSER; VALID UNTIL '2026-12-31'; PASSWORD '...'
CREATE ROLE reporting LOGIN PASSWORD '...' NOSUPERUSER NOCREATEDB; ALTER ROLE app SET statement_timeout = '5s' GRANT / REVOKEテーブル / スキーマ / データベース / 関数に対し権限を付与;列レベルも可能。
GRANT SELECT, INSERT ON TABLE ...; GRANT USAGE ON SCHEMA ...; WITH GRANT OPTION
GRANT SELECT ON ALL TABLES IN SCHEMA public TO reporting;\dt <schema>.* / pg_hba.confsearch_path と可視オブジェクトを調整(\dt public.*);pg_hba.conf が接続可否を制御。
SHOW search_path; ALTER ROLE app IN DATABASE app SET search_path = app, public; pg_hba.conf hostssl all all 0.0.0.0/0 scram-sha-256
ALTER ROLE app SET search_path = app, public;チートシート バージョン 1.0.0
PostgreSQL 14+ に対応