PostgreSQL 命令速查
psql 元命令 / DDL / DML / JSON
psql 元命令 / DDL / DML / JSON
在 psql 命令行里敲 `\dt` 却忘了表名,或者写 `UPDATE` 时被 `WHERE` 子句卡住——这个速查表把元命令、DDL 和 DML 按场景分组,每条都附真实输出示例。不依赖后端,页面加载完即离线可用,适合在终端旁开个标签页对照敲命令,也适合面试前快速过一遍常用语法边界。
产品经理凌晨两点发来需求:用户画像表要加一个『最近登录时间』字段。DBA 小陈在 TIMESTAMP 和 TIMESTAMPTZ 之间犹豫——业务数据未来可能跨时区,但当前只服务国内用户。他打开本工具的 DDL 速查,对比两种类型的存储方式、时区处理逻辑和索引性能差异,5 分钟内确定用 TIMESTAMPTZ,避免后续迁移时数据错乱。
运维值班的老张在凌晨三点执行清理脚本时,误将生产环境 orders 表里今天所有未支付订单 delete 了。业务方 8 点要核对数据。他翻出本工具的 DML 章节,快速确认 DELETE 不带 WHERE 子句的不可逆性,转而用 pg_dump 从昨晚全量备份中恢复,并用 COPY 命令将丢失的 237 条记录重新插入,赶在晨会前恢复数据。
公司核心报表页面在月底结算时加载超过 30 秒,开发组长需要排查。他在本工具中查到 EXPLAIN ANALYZE 的完整语法和输出字段含义——包括 rows、width、cost 的实际值与估算值对比。通过对比发现某 JOIN 缺少索引导致嵌套循环扫描了 120 万行,添加复合索引后查询降至 200 毫秒。
市场部要一份过去三个月所有付费用户的订单明细,数据量约 80 万行。BI 工程师用本工具查到 COPY TO 命令的正确写法——指定 DELIMITER ',' 和 CSV HEADER,并设置 QUOTE '"' 避免字段内逗号引发错列。原本用 SELECT INTO OUTFILE 需要 3 分钟,改用 COPY 后 12 秒导出完毕,且不经过应用层内存。
数据库从 9.6 升级到 14,需要将 20 张表的字符集从 SQL_ASCII 改为 UTF8。DBA 小王在本工具中找到 ALTER TABLE 的完整语法树,以及 ALTER COLUMN TYPE 的 USING 子句写法。他写了一个脚本遍历系统表 pg_class,用 ALTER TABLE t ALTER COLUMN c TYPE text USING c::text 批量转换,避免逐表手动操作导致遗漏。
| 输入 | 输出 | 说明 |
|---|---|---|
| \l | 列出所有数据库名称、所有者、编码、字符集等 | 常规:最常用的元命令,查看当前集群有哪些数据库 |
| \dt | 列出当前数据库的所有表 | 常规:查看表清单,区分视图、序列等对象用 \d 系列 |
| \d users | 表 "public.users" 的列名、类型、非空约束、默认值等 | 常规:查看单表结构,比 \dt 更详细 |
| \dt *.orders | 列出所有 schema 下名称含 orders 的表 | 边界:通配符 * 匹配任意 schema,适合多 schema 数据库 |
| \x on | 扩展显示模式已开启(后续查询结果按行展开) | 边界:切换显示模式,宽表或列数多时必用,避免折行 |
| \! clear | 清空终端屏幕(执行 shell 命令) | 边界:\! 可执行任意 shell 命令,不仅是 clear,但注意安全 |
| \dt+ pg_catalog.pg_class | 显示表大小、描述等额外信息(+ 后缀) | 易错:+ 后缀在 \d 系列中表示显示更多属性,但 pg_catalog 表通常无描述 |
| \set PROMPT1 '%n@%/%R%x%# ' | 提示符变为 user@dbname=# | 易错:\set 修改变量,语法易混淆(缺 % 或引号会导致不生效) |
1.psql 元命令后漏掉分号,导致命令未执行
\dt users\dt users;psql 元命令(反斜杠开头)本身不需要分号结束,但若后面紧跟 SQL 语句或换行前未加回车,某些上下文会吞掉后续输入。标准做法是每条元命令独立一行,或用分号明确终止。
2.UPDATE 忘记 WHERE 子句,全表被更新
UPDATE employees SET salary = 50000;UPDATE employees SET salary = 50000 WHERE id = 123;PostgreSQL 的 UPDATE 不加 WHERE 会作用于所有行。这是 DML 中最常见的数据灾难,生产环境应养成先 SELECT 确认再 UPDATE 的习惯。
3.DELETE 同样忘记 WHERE,全表被清空
DELETE FROM orders;DELETE FROM orders WHERE status = 'cancelled';DELETE 不加 WHERE 等于 TRUNCATE(但更慢且产生 WAL)。很多新手以为会提示确认,实际上直接执行。建议先写 WHERE 再补 FROM 部分。
4.字符串字面量用双引号而非单引号
SELECT * FROM users WHERE name = "Alice";SELECT * FROM users WHERE name = 'Alice';SQL 标准中双引号用于标识符(表名、列名),单引号用于字符串字面量。用双引号包裹字符串会导致 PostgreSQL 将其解释为列名,报错 column "Alice" does not exist。
5.INSERT 时列数与 VALUES 数量不匹配
INSERT INTO users (name, age) VALUES ('Bob');INSERT INTO users (name, age) VALUES ('Bob', 30);PostgreSQL 在编译期检查列数与值数量是否一致。少写一个值会报 "INSERT has more target columns than expressions"。建议始终显式列出列名。
6.GROUP BY 中遗漏非聚合列
SELECT department, AVG(salary) FROM employees;SELECT department, AVG(salary) FROM employees GROUP BY department;SQL 标准要求 SELECT 中所有非聚合列必须出现在 GROUP BY 中。PostgreSQL 默认拒绝这种查询(比 MySQL 严格),报错 "column must appear in the GROUP BY clause"。
7.使用 = NULL 而非 IS NULL 判断空值
SELECT * FROM users WHERE email = NULL;SELECT * FROM users WHERE email IS NULL;SQL 中 NULL 代表未知值,任何与 NULL 的比较(=、<>、<)都返回 NULL(即 false)。必须用 IS NULL 或 IS NOT NULL 来检测。
8.在 psql 中忘记用 \c 切换数据库
连接到默认数据库后直接执行 DDL,操作了错误数据库\c mydb;psql 启动时连接的数据库由命令行参数 -d 或环境变量 PGDATABASE 决定。如果不显式切换,DDL/DML 会作用在当前数据库上。\c 可快速切换。
9.ALTER TABLE 修改列类型时丢失数据
ALTER TABLE products ALTER COLUMN price TYPE integer;ALTER TABLE products ALTER COLUMN price TYPE numeric(10,2) USING price::numeric;直接转换类型可能因隐式转换规则导致数据截断或失败。加上 USING 子句可显式控制转换逻辑,避免意外丢失小数部分。
10.在事务中执行 DDL 后忘记 COMMIT
BEGIN; CREATE TABLE temp (...); -- 然后直接关闭连接BEGIN; CREATE TABLE temp (...); COMMIT;PostgreSQL 默认每个语句自动提交,但显式 BEGIN 后进入事务块。DDL 在事务内也是原子操作,不 COMMIT 则回滚。很多用户误以为 DDL 自动提交,导致表未创建。
SELECT column1, column2, ... FROM table_name WHERE condition;
column1, column2, ...要查询的列名,可用 * 表示所有列table_name要查询的表名condition筛选条件,如 id = 1查询 users 表中年龄大于 30 的用户姓名和邮箱:SELECT name, email FROM users WHERE age > 30; 返回所有满足条件的行。
元命令(以反斜杠开头,如 \dt、\l)是 psql 客户端内置的快捷指令,不经过服务器解析 SQL,直接在客户端执行,用于查看数据库对象列表、切换连接等管理操作。SQL 语句(SELECT、CREATE TABLE)发给服务器执行,用于数据查询和 DDL/DML。简单判断:想看元信息(有哪些表、索引大小)用元命令;想查数据、改结构用 SQL。同一个页面上方切换标签可分别查询两类。
\dt 默认只显示当前 schema(通常是 public)下的表。如果表建在其它 schema(如 myschema.table1),需要先执行 set schema 'myschema'; 或用 \dt myschema.* 查看。另外,如果当前用户没有该表的 SELECT 权限,\dt 也不会列出。检查权限:\dn 列出所有 schema,\du 查看当前用户角色。
用 \d 表名,一行搞定。它会列出字段名、数据类型、非空约束、默认值,以及主键、索引、外键、触发器。如果只想看字段和类型,\d+ 表名 还会额外显示存储参数和统计信息。注意:\d 后面不要加分号,它是元命令不是 SQL。
说明同名表已经存在。PostgreSQL 不允许同一个 schema 下建两个同名表。先确认是否真的需要新表:用 \dt 查看已有表。如果是要覆盖旧表,用 DROP TABLE IF EXISTS 表名; 再 CREATE TABLE;如果只是要清空数据,用 TRUNCATE 表名; 比删重建快且不会丢失索引。注意大小写:PostgreSQL 默认把未加引号的标识符转成小写,如果建表时用了 "MyTable",查询时也必须加引号。
最常见的原因是事务未提交。如果连接开启了 BEGIN; 执行 INSERT 后没有执行 COMMIT;,数据只对当前会话可见,其它连接查不到。检查方法:在同一个会话里执行 SELECT * FROM 表名; 看能不能查到,如果查到但另开窗口查不到,就是没提交。另外,检查是否插入了错误的 schema(如插到了 public 但查的是 myschema)。本工具所有示例都默认自动提交,但生产环境建议显式控制事务。
结果基本一致,都列出所有数据库名称、所有者、编码、collation 等。区别在于:\l 是元命令,psql 内部调用 pg_database 并格式化输出,更易读;SELECT * FROM pg_database; 返回原始行,可能包含更多内部字段(oid、datconnlimit 等)。日常管理用 \l 更快,写脚本或需要过滤特定属性时用 SQL。本工具在「元命令」标签下展示 \l 的典型输出格式。
PostgreSQL 没有内置回收站。一旦 COMMIT,DELETE 的数据默认无法通过普通 SQL 恢复。补救方法(必须在删除后立即操作):1. 如果数据库开启了归档日志且有时间点恢复(PITR)能力,可将库恢复到删除前的时间点;2. 如果删除前有 pg_dump 备份,从备份恢复;3. 如果事务还没提交,执行 ROLLBACK; 即可撤销。建议:重要操作前先用 BEGIN; 开启事务,确认结果正确再 COMMIT;或先 SELECT 查看要删除的行,再用 DELETE 配合 WHERE 子句精确删除。
不会。本工具(FE 实现)所有 SQL 和元命令都在浏览器本地执行,通过 PostgreSQL 的 WebSocket 或 HTTP 直连你填写的数据库地址,不经过任何中转服务器。连接信息(主机、端口、用户名、密码)仅存储在浏览器内存中,关闭页面即清除。如果不放心,可查看浏览器开发者工具的网络面板,确认没有任何请求发到第三方域名。离线环境也可使用。
隐私保证所有计算与处理均在你的浏览器本地完成,输入数据不会上传服务器,也不会保存或共享。