Skip to content

psql 元命令(\d / \dt / \du) ​

psql 是 PostgreSQL 的官方命令行客户端。除了执行 SQL,它还提供了一组以反斜杠开头的「元命令(meta-command)」,用于探查数据库结构、查看权限、切换输出格式、执行脚本与变量替换。这些命令不需要分号结尾,也不发送给服务器——除了 \d 系列会转换为系统目录查询外,其余大多由 psql 本地解析。掌握元命令是日常运维与排障的基本功。

前置知识

阅读本节前,建议先了解:COALESCE / NULLIF / GREATEST / LEAST

基础概念 ​

概念术语说明
元命令Meta-Command以 \ 开头的客户端命令,由 psql 本地解析
描述命令\d Family查看表、索引、序列、视图、函数等对象的定义
系统目录System Catalogpg_class、pg_attribute 等存放元数据的系统表
扩展显示Expanded Display\x 把结果按「列名 | 值」竖排,适合宽表
输出格式Output Format\pset 控制对齐、边框、NULL 显示、分页等
变量psql Variable\set 定义的客户端变量,用 :'var' 安全插值
脚本执行\i / \ir执行 SQL 文件;\ir 相对当前脚本路径解析
条件执行\if Family\if / \elif / \else / \endif 控制脚本分支
启动配置.psqlrc每次启动自动执行的初始化脚本
监听刷新\watch周期性重复执行上一条查询并刷新输出

元命令与 SQL 的区别:

  • 元命令不需要分号,一行一条(除非用 \ 续行)。
  • 元命令不做 SQL 语法解析,参数按空白切分。
  • 元命令大多不发给服务器,只有 \d 系列、\copy、\watch 等会与服务器交互。
bash
# 在 psql 交互式会话中,元命令直接输入即可
\conninfo          # 显示当前连接信息
\dt                # 列出当前 schema 的表
\d products        # 查看 products 表的定义

语法与用法 ​

常用元命令速查(按用途分组):

用途命令说明
帮助\?列出所有元命令
帮助\h SQL查看某条 SQL 的语法
列出对象\d列出所有可见对象
列出表\dt列出表(含 schema、类型、属主)
列出索引\di列出索引
列出序列\ds列出序列
列出视图\dv列出视图
列出物化视图\dm列出物化视图
列出函数\df列出函数(含参数与返回类型)
列出 schema\dn列出 schema
列出扩展\dx列出已安装扩展
列出角色\du列出角色与权限
列出权限\dp列出表/视图的访问权限
查看定义\d+ name查看对象详细定义(含注释、大小)
含系统对象\dS加 S 后缀包含系统对象
显示原始 SQL\sf func显示函数定义源码
切换格式\x切换扩展显示(竖排/横排)
设置参数\pset调整输出格式
计时\timing开关 SQL 执行计时
执行文件\i file执行 SQL 文件
执行文件\ir file相对当前脚本目录执行
输出重定向\o file把后续结果写入文件
客户端导入导出\copy客户端侧 COPY,支持文件路径
重复执行\g / \gx重新执行查询缓冲
周期刷新\watch 5每 5 秒重复执行上一条查询
编辑缓冲\e用编辑器打开当前查询缓冲
定义变量\set v val定义客户端变量
引用变量:'v' / :"v"安全插值(带引号 / 标识符)
条件\if \elif \else \endif脚本条件分支
连接\c dbname切换数据库
连接信息\conninfo显示当前连接
退出\q退出 psql
bash
# 最常用的探查三连
\dt                  # 我有哪些表?
\d products          # 这张表长什么样?
\du                  # 有哪些角色、权限如何?

详细说明 ​

\d 系列:对象探查 ​

\d 是「describe」的缩写,是使用频率最高的一组命令。它支持通配符匹配。

bash
# 列出所有对象(表、视图、序列、索引都在内)
\d

# 只看表;*.* 表示所有 schema
\dt
\dt *.*

# 通配符匹配表名
\dt public.order*

# 查看单个表的完整定义(列、类型、约束、索引、触发器、属主)
\d products

\d products 的典型输出:

text
                    Table "public.products"
  Column  |          Type          | Collation | Nullable | Default
----------+------------------------+-----------+----------+--------------------------------------
 id       | integer                |           | not null | generated always as identity
 sku      | text                   |           | not null |
 name     | text                   |           | not null |
 price    | numeric(10,2)          |           |          |
 stock    | integer                |           | not null | 0
Indexes:
    "products_pkey" PRIMARY KEY, btree (id)
    "products_sku_key" UNIQUE CONSTRAINT, btree (sku)

加 + 后缀会输出更多信息:注释、存储参数、表大小、访问方式等。

bash
\d+ products
text
                                             Table "public.products"
  Column  |          Type          | ... | Storage  | Stats target | Description
----------+------------------------+-----+----------+--------------+-------------
 id       | integer                | ... | plain    |              |
 price    | numeric(10,2)          | ... | main     |              |
...
Has OIDs: no
Options: autovacuum_enabled=true

\dt / \di / \ds / \dv:按类型列举 ​

\d + 类型字母是固定组合,记住后缀字母即可:

后缀含义英文
t表table
i索引index
s序列sequence
v视图view
m物化视图materialized view
f函数function
nschemanamespace
x扩展extension
p权限privileges
u角色user
bash
# 只看索引
\di

# 只看当前库的扩展
\dx

# 列出所有 schema
\dn

# 列出角色
\du

\du 与权限查看 ​

\du 输出角色列表及其属性。

text
                             List of roles
 Role name  |                         Attributes
------------+------------------------------------------------------------
 app_user   | 
 postgres   | Superuser, Create role, Create DB, Replication, Bypass RLS
 readonly   | Cannot login

要查看某张表的具体授权情况,用 \dp 或 \z:

bash
\dp products
\z products
text
                             Access privileges
 Schema |   Name   |   Type   |     Access privileges     | Column privileges
--------+----------+----------+---------------------------+-------------------
 public | products | table    | postgres=arwdDxt/postgres+| 
        |          |          | app_user=arwd/postgres    |

权限字母含义:a = INSERT、r = SELECT、w = UPDATE、d = DELETE、D = TRUNCATE、x = REFERENCES、t = TRIGGER。

\x:扩展显示 ​

宽表在终端里会被截断或换行错乱,\x 切换为竖排显示,一行一个字段,非常适合列多的表。

bash
\x                 # 开启
SELECT * FROM products WHERE sku = 'SKU-1001';
\x                 # 关闭
text
-[ RECORD 1 ]-----------
id    | 1
sku   | SKU-1001
name  | 27 英寸显示器
price | 1299.00
stock | 12

也可以用 \pset expanded on 达到同样效果,\x auto 则在输出过宽时自动切换。

\pset 与输出控制 ​

\pset 控制结果集的呈现方式,常用的有:

参数作用常用值
format输出格式aligned、unaligned、csv、json、html
expanded竖排显示on / off / auto
nullNULL 的显示文本如 NULL、(空)
border边框样式0、1、2
pager分页器on / off
tuples_only只输出数据行on / off
fieldsep分隔符,、|
bash
# 导出为 CSV 风格
\pset format csv
\pset null '(空)'
SELECT sku, name, price FROM products LIMIT 3;

# 只输出数据、无表头与边框(便于脚本解析)
\pset tuples_only on
\pset format unaligned
SELECT sku FROM products;

变量与安全插值 ​

\set 定义客户端变量,用 :'var' 插入为字符串字面量(自动加引号并转义),:"var" 插入为标识符。

bash
# 定义变量
\set tbl products
\set sku 'SKU-1001'

# 作为标识符(不加引号)
SELECT * FROM :"tbl" WHERE sku = :'sku';

# 查看已定义变量
\set

# 取消变量
\unset tbl

关键安全点:用 :'var' 而不是字符串拼接,可以避免 SQL 注入。因为 psql 会正确转义单引号。

bash
# 危险!若 :val 含单引号会语法错误或被注入
SELECT * FROM products WHERE name = ':val';   -- 错误!这是字面量文本
# 正确
SELECT * FROM products WHERE name = :'val';

\i / \ir / \o / \copy:脚本与文件 ​

bash
# 执行 SQL 文件(相对当前工作目录)
\i /path/to/schema.sql

# 执行 SQL 文件(相对当前脚本所在目录)——脚本内嵌套调用时更安全
\ir ./seed.sql

# 把后续查询结果写入文件
\o /tmp/result.txt
SELECT * FROM products;
\o                # 结束重定向,恢复标准输出

# 客户端侧 COPY:可读写客户端本地文件
\copy products TO '/tmp/products.csv' WITH (FORMAT csv, HEADER true)
\copy products FROM '/tmp/products.csv' WITH (FORMAT csv, HEADER true)

\copy 与服务器端 COPY 的区别:\copy 由 psql 客户端读写文件,因此不需要超级用户权限,也不需要文件位于服务器上。

\g / \gx / \watch:重复与刷新 ​

bash
# \g 重新执行查询缓冲
SELECT * FROM products;

# \gx 以竖排方式执行
\gx

# \watch 周期执行上一条查询(默认 2 秒)
SELECT count(*) FROM orders;
\watch 5          # 每 5 秒刷新一次;Ctrl+C 退出

\watch 常用于观察 pg_stat_activity、锁等待、复制延迟等动态指标。

\e / \ef / \sf:编辑与查看定义 ​

bash
# 用默认编辑器打开查询缓冲
\e

# 编辑函数定义并自动重建
\ef my_function

# 显示函数的定义源码
\sf my_function

\if / \elif / \else / \endif:脚本条件 ​

psql 支持在脚本中做条件判断,配合 \set 变量可实现简单的流程控制。

bash
\set env 'prod'

\if :'env' = 'prod'
  \echo '生产环境:只读操作'
  \set readonly true
\elif :'env' = 'test'
  \echo '测试环境:可写'
  \set readonly false
\else
  \echo '未知环境'
\endif

.psqlrc:启动配置 ​

~/.psqlrc 在每次启动交互式会话时自动执行,适合放置常用设置。

ini
-- ~/.psqlrc
\set HISTSIZE 10000
\pset null '(NULL)'
\pset border 2
\timing on
\set PROMPT1 '%n@%/%R%# '
\set COMP_KEYWORD_CASE upper

用 psql -X 可以跳过 .psqlrc 加载,做问题排查时非常有用。

反斜杠续行与批量命令 ​

元命令可以用 \ 结尾续行,参数也可以多行书写。

bash
# 内容含空格或反斜杠时用单引号包裹
\echo 'Hello, World'

# 查看某条 SQL 的命令语法
\h CREATE INDEX

实战示例 ​

步骤 1:建库建表并造数据 ​

sql
CREATE DATABASE demo;

\c demo

CREATE TABLE products (
  id    integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  sku   text    NOT NULL UNIQUE,
  name  text    NOT NULL,
  price numeric(10, 2),
  stock integer NOT NULL DEFAULT 0
);

CREATE INDEX idx_products_price ON products (price);

CREATE TABLE orders (
  id         integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  order_no   text NOT NULL,
  product_id integer REFERENCES products (id),
  qty        integer NOT NULL
);

INSERT INTO products (sku, name, price, stock) VALUES
  ('SKU-1001', '27 英寸显示器', 1299.00, 12),
  ('SKU-1002', '机械键盘',       399.00, 30),
  ('SKU-1003', '无线鼠标',       159.00,  0);

步骤 2:探查表结构 ​

bash
\d products
text
                    Table "public.products"
  Column  |     Type      | Collation | Nullable | Default
----------+---------------+-----------+----------+--------------------------------------
 id       | integer       |           | not null | generated always as identity
 sku      | text          |           | not null |
 name     | text          |           | not null |
 price    | numeric(10,2) |           |          |
 stock    | integer       |           | not null | 0
Indexes:
    "products_pkey" PRIMARY KEY, btree (id)
    "products_sku_key" UNIQUE CONSTRAINT, btree (sku)
    "idx_products_price" btree (price)
Referenced by:
    TABLE "orders" CONSTRAINT "orders_product_id_fkey" FOREIGN KEY (product_id) REFERENCES products(id)

步骤 3:列举对象与角色 ​

bash
\dt
\di
\du
text
          List of relations
 Schema |   Name   | Type  |  Owner
--------+----------+-------+----------
 public | orders   | table | postgres
 public | products | table | postgres
(2 rows)

                   List of indexes
 Schema |        Name         | Type  |  Owner   |  Table
--------+---------------------+-------+----------+----------
 public | idx_products_price  | index | postgres | products
 public | orders_pkey         | index | postgres | orders
 public | products_pkey       | index | postgres | products
 public | products_sku_key    | index | postgres | products
(4 rows)

                             List of roles
 Role name |                         Attributes
-----------+------------------------------------------------------------
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS
(1 row)

步骤 4:竖排显示与格式控制 ​

bash
\x
SELECT * FROM products WHERE sku = 'SKU-1001';
text
-[ RECORD 1 ]-----------
id    | 1
sku   | SKU-1001
name  | 27 英寸显示器
price | 1299.00
stock | 12
bash
\pset format csv
\pset null '(空)'
SELECT sku, name, price FROM products ORDER BY sku;
text
sku,name,price
SKU-1001,27 英寸显示器,1299.00
SKU-1002,机械键盘,399.00
SKU-1003,无线鼠标,159.00

步骤 5:变量插值 ​

bash
\set tbl products
\set min_price 200

SELECT sku, name, price
FROM :"tbl"
WHERE price > :min_price
ORDER BY price;
text
   sku    |    name    |  price
----------+------------+---------
 SKU-1002 | 机械键盘    |  399.00
 SKU-1001 | 27 英寸显示器 | 1299.00
(2 rows)

步骤 6:脚本执行与结果导出 ​

bash
# 把查询结果导出为 CSV
\pset format csv
\o /tmp/products_report.csv
SELECT sku, name, coalesce(price, 0) AS price FROM products ORDER BY sku;
\o

# 查看文件(在 shell 中)
\! head -n 3 /tmp/products_report.csv
text
sku,name,price
SKU-1001,27 英寸显示器,1299.00
SKU-1002,机械键盘,399.00

注意事项 ​

  • 元命令不加分号。 加了分号会被当作 SQL 文本的一部分,导致语法错误或行为不符预期。
bash
\dt;    -- 错误!分号会被当作参数
  • 元命令不支持事务内的服务器端回滚。 元命令是客户端行为,BEGIN 中的 \d 不会回滚,且 \copy 走单独的连接上下文。

  • \d 系列查的是系统目录,权限不足时对象不可见。 看不到某张表可能只是没有权限,而非表不存在。

  • \i 与 \ir 的路径解析不同。 \i 相对当前工作目录,\ir 相对当前正在执行的脚本目录;嵌套脚本一律用 \ir。

bash
\i ./sub/init.sql     -- 相对进程工作目录,易出错
\ir ./sub/init.sql    -- 相对本脚本目录,推荐
  • 变量插值必须用 :'var'。 直接写 :var 或字符串拼接会带来语法错误与注入风险。
bash
-- 错误!这是普通字符串,不会替换变量
WHERE name = ':val'
-- 正确
WHERE name = :'val'
  • \pset format 等设置在会话内持续生效。 若在脚本中修改,记得用完恢复,否则影响后续输出。

  • \x 是开关,不是固定开启。 连续按两次会回到横排,脚本中建议显式写 \x on / \x off。

  • \watch 会持续占用连接。 忘记 Ctrl+C 可能导致连接被长期占用,生产环境注意使用频率与超时。

  • 不要在生产库直接执行 \copy ... FROM。 客户端路径导入同样会写入数据,误用可能污染生产数据。

最佳实践 ​

  1. 把常用设置写进 ~/.psqlrc,统一 NULL 显示、边框与计时,减少重复输入。
ini
-- ~/.psqlrc
\pset null '(NULL)'
\pset border 2
\timing on
  1. 排查问题的第一步固定为「三连」:\conninfo、\dt、\d 表名,快速建立环境与结构认知。
bash
\conninfo
\dt
\d products
  1. 宽表查询一律先 \x,避免终端换行错乱导致误读数据。
bash
\x on
SELECT * FROM pg_stat_activity WHERE state <> 'idle';
  1. 脚本中一律用 \ir,保证无论从哪个目录调用都能正确定位相对文件。

  2. 变量插值统一用 :'var' / :"var",绝不拼接字符串,从源头规避注入。

bash
\set schema public
SELECT count(*) FROM :"schema".products;
  1. 用 \dp 定期复核权限,尤其是生产库中对 public schema 的默认授权。
bash
\dp
\dn+
  1. 导出数据优先用 \copy 而非服务器端 COPY,免去超级用户与服务器文件路径的约束。
bash
\copy (SELECT sku, name FROM products) TO '/tmp/out.csv' WITH (FORMAT csv, HEADER true)
  1. 在 CI 或迁移脚本中用 psql -v ON_ERROR_STOP=1,让任意 SQL 失败立即中止,避免半成品状态。
bash
psql -v ON_ERROR_STOP=1 -d demo -f migrate.sql
  1. 用 \timing + \watch 组合做轻量性能观察,快速定位慢查询与锁等待,无需额外工具。
bash
\timing on
SELECT count(*) FROM orders;
\watch 2

下一节

继续学习:EXPLAIN 执行计划

参考链接 ​