クエリバッファと\gの関係
psqlは;を入力するまでの内容を「クエリバッファ」に溜めておき、;または\gが入力された時点でサーバーへ送信する。\gはクエリバッファの内容を明示的に実行するメタコマンドである。
testdb=# SELECT id, name FROM users WHERE id = 1
testdb-# \g
id | name
----+-------
1 | alice
(1 row)
;の代わりに\gを使っても結果は同じである。クエリバッファは実行後もそのまま保持されるため、続けて\gだけを入力すると直前のクエリを再実行できる。
\gにファイル名を指定して結果を保存する
\gにファイル名を指定すると、画面表示の代わりに結果をファイルへ書き込む。
testdb=# SELECT * FROM users LIMIT 1;
id | name | email
----+-------+-------------------
1 | alice | alice@example.com
(1 row)
testdb=# \g /tmp/result.txt
$ cat /tmp/result.txt
id | name | email
----+-------+-------------------
1 | alice | alice@example.com
(1 row)
2回目の\gはクエリバッファに残っている直前のクエリを再実行し、その結果をファイルに書き込んでいる。パイプ|を指定すればシェルコマンドへ結果を渡すこともできる。
参考: 【PostgreSQL】psqlでクライアント側からCSVを入出力する
\gxで1回だけ展開表示する
\gxは\gと同じくクエリバッファを実行するが、その実行だけ強制的に展開表示(縦持ち表示)にする。
testdb=# SELECT id, name FROM users WHERE id = 1
testdb-# \gx
-[ RECORD 1 ]
id | 1
name | alice
\xでセッション全体の表示形式を切り替えるのとは違い、\gxはその1回の実行だけ展開表示になる。\xの設定状態を変更しないため、普段は通常表示で使いつつ、特定のクエリだけ列を縦に並べて確認したい場合に使う。
参考: 【PostgreSQL】psqlでクエリ結果を縦持ち表示に切り替える
\gdescでクエリを実行せずに結果の型だけ確認する
\gdescはクエリバッファの内容を実際には実行せず、返ってくる列名とデータ型だけを表示する。
testdb=# SELECT * FROM users LIMIT 1
testdb-# \gdesc
Column | Type
--------+---------
id | integer
name | text
email | text
(3 rows)
INSERTやUPDATEを含む複雑なクエリの結果セットの形だけを事前に確認したい場合や、アプリケーションのコード生成でカラム定義を調べたい場合に使う。実データへのアクセスなしに構造だけ調べられる。
\gsetでクエリ結果をpsql変数に格納する
\gsetはクエリ結果(1行)の各列を、同名のpsql変数に格納する。
testdb=# SELECT count(*) AS user_count, max(id) AS max_id FROM users;
testdb=# \gset
testdb=# \echo :user_count
2
testdb=# \echo :max_id
2
列名がそのまま変数名になるため、ASで分かりやすい別名を付けておくと扱いやすい。格納した変数はその後のクエリ内で:変数名として参照できる。
testdb=# SELECT * FROM users WHERE id = :max_id;
id | name | email
----+------+-----------------
2 | bob | bob@example.com
(1 row)
引数にプレフィックスを指定すると、変数名の頭に付加できる。複数のクエリ結果を格納して名前が衝突するのを避けたい場合に使う。
testdb=# SELECT count(*) AS cnt FROM users;
testdb=# \gset user_
testdb=# \echo :user_cnt
2
\gsetは結果が複数行あるとエラーになるため、集計クエリなど1行だけを返すクエリと組み合わせて使う。
\gexecでクエリ結果をSQLとして実行する
\gexecはクエリ結果の各セルをSQL文として順番に実行する。動的にSQL文そのものを生成して実行したい場合に使う。
testdb=# SELECT 'SELECT count(*) FROM ' || tablename || ';'
testdb-# FROM pg_tables
testdb-# WHERE schemaname = 'public' AND tablename IN ('users', 'orders');
?column?
------------------------------
SELECT count(*) FROM orders;
SELECT count(*) FROM users;
(2 rows)
testdb=# \gexec
count
-------
3
(1 row)
count
-------
2
(1 row)
生成された2つのSELECT count(*)文が順番に実行され、それぞれの結果が表示される。pg_tablesから動的にテーブル一覧を取得し、テーブルごとに同じ操作をするスクリプトを組む際などに使う。実行対象がテーブルを削除する文になりうる場合は、\gexecする前に生成されたSQL文をよく確認する。
