Skip to content

附录


附录 A:SQL 语句执行顺序

写 SQL 时的书写顺序和数据库的实际执行顺序是不同的。理解这个差异能帮你写出更正确的 SQL,也能理解为什么某些写法会报错。

对照表

执行顺序子句做什么
1FROM / JOIN确定数据来源,执行表连接
2WHERE过滤行(在分组之前)
3GROUP BY将行分组
4HAVING过滤分组(在分组之后)
5SELECT选择列、计算表达式、去重(DISTINCT)
6ORDER BY排序
7LIMIT / OFFSET限制返回行数

图示

书写顺序                    执行顺序

SELECT    ──────┐     ┌──── FROM / JOIN    ①
FROM      ──┐   │     │
JOIN      ──┘   │     ├──── WHERE           ②
WHERE     ──────┤     │
GROUP BY  ──────┤     ├──── GROUP BY        ③
HAVING    ──────┤     │
                │     ├──── HAVING          ④
                └─────┤
                      ├──── SELECT          ⑤
ORDER BY  ────────────┤
                      ├──── ORDER BY        ⑥
LIMIT     ────────────┤
                      └──── LIMIT / OFFSET  ⑦

常见因执行顺序导致的错误

sql
-- 错误:WHERE 中不能用 SELECT 定义的别名(WHERE 先于 SELECT 执行)
SELECT name, age * 2 AS double_age FROM students
WHERE double_age > 40;
-- ERROR: column "double_age" does not exist

-- 正确写法
SELECT name, age * 2 AS double_age FROM students
WHERE age * 2 > 40;

-- 正确:ORDER BY 中可以用别名(ORDER BY 在 SELECT 之后执行)
SELECT name, age * 2 AS double_age FROM students
ORDER BY double_age DESC;

附录 B:psql 完整快捷命令速查

信息查看

命令作用
\l\list列出所有数据库
\c dbname切换到指定数据库
\dt列出当前 schema 的所有表
\dt+列出所有表(含大小信息)
\d tablename查看表结构
\d+ tablename查看表详细结构(含存储信息)
\di列出所有索引
\dv列出所有视图
\df列出所有函数
\du列出所有角色 / 用户
\dn列出所有 schema
\ds列出所有序列

功能控制

命令作用
\timing开启 / 关闭查询耗时显示
\x开启 / 关闭扩展显示模式(宽表变竖排)
\a切换对齐 / 不对齐输出
\pset border 2设置表格边框样式

文件与编辑

命令作用
\i filename.sql执行 SQL 文件
\o filename.txt将输出重定向到文件
\e用外部编辑器写 SQL
\s查看命令历史

系统操作

命令作用
\! command执行系统命令(如 \! ls
\cd directory切换工作目录
\q退出 psql
\?显示所有反斜杠命令的帮助
\h SQL命令显示某个 SQL 命令的帮助(如 \h CREATE TABLE

附录 C:推荐学习路径

七步走完 PostgreSQL 入门

第一步  安装环境,用 psql 连上数据库           → 第 1 章
        预计时间:30 分钟
        目标:能执行 SELECT version(); 看到结果

第二步  建库建表,理解数据类型和约束             → 第 2 章
        预计时间:45 分钟
        目标:能独立建一张包含各种约束的表

第三步  增删改数据                              → 第 3 章
        预计时间:30 分钟
        目标:熟练使用 INSERT/UPDATE/DELETE

第四步  SELECT 查询——本教程的核心               → 第 4 章
        预计时间:2 小时
        目标:掌握 WHERE/ORDER BY/GROUP BY/JOIN/子查询

第五步  理解索引和 EXPLAIN                      → 第 5 章
        预计时间:30 分钟
        目标:能用 EXPLAIN 判断查询是否走了索引

第六步  了解事务,能写 BEGIN/COMMIT              → 第 6 章
        预计时间:30 分钟
        目标:理解 ACID,能手写事务

第七步  探索高级特性 + 基本运维                  → 第 7~8 章
        预计时间:1 小时
        目标:知道 JSONB/窗口函数/CTE 的存在和用法

总计约 5~6 小时,即可建立完整的 PostgreSQL 知识框架。

进阶方向

完成本教程后,可以根据自己的方向深入:

方向建议学习内容
后端开发ORM(SQLAlchemy / Prisma)、连接池(PgBouncer)、数据库迁移
数据分析窗口函数进阶、CTE 递归、物化视图、COPY 批量导入
数据库运维性能调优(pg_stat_statements)、主从复制、备份策略、监控告警
全栈开发Supabase / Neon(云原生 PostgreSQL)、PostgREST(自动生成 REST API)

推荐资源

资源说明
PostgreSQL 官方文档最权威的参考手册
PostgreSQL Tutorial英文入门教程,示例丰富
Use The Index, Luke索引优化专题,非常推荐
pgexercises.comPostgreSQL 在线练习题
Explain VisualizerEXPLAIN 结果可视化工具

附录 D:本教程示例数据库完整建表脚本

以下脚本一次性创建本教程使用的所有表和示例数据,方便你从零开始练习。

sql
-- ============================================
-- PostgreSQL 入门教程 - 示例数据库
-- ============================================

-- 创建数据库
-- CREATE DATABASE school;
-- \c school

-- 学生表
CREATE TABLE students (
    id          INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    name        VARCHAR(50) NOT NULL,
    email       VARCHAR(100) UNIQUE,
    age         INTEGER CHECK (age BETWEEN 1 AND 150),
    is_active   BOOLEAN DEFAULT true,
    enrolled_at TIMESTAMPTZ DEFAULT NOW()
);

-- 课程表
CREATE TABLE courses (
    id          INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    student_id  INTEGER REFERENCES students(id) ON DELETE CASCADE,
    course_name VARCHAR(100) NOT NULL,
    score       NUMERIC(5,2)
);

-- 账户表(用于事务练习)
CREATE TABLE accounts (
    id      INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    name    VARCHAR(50) NOT NULL,
    balance NUMERIC(10,2) NOT NULL CHECK (balance >= 0)
);

-- 事件表(用于 JSONB 练习)
CREATE TABLE events (
    id         INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    event_type VARCHAR(50),
    data       JSONB,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

-- ============================================
-- 插入示例数据
-- ============================================

INSERT INTO students (name, email, age) VALUES
    ('张三', 'zhangsan@example.com', 20),
    ('李四', 'lisi@example.com', 22),
    ('王五', 'wangwu@example.com', 21),
    ('赵六', 'zhaoliu@example.com', 23),
    ('孙七', 'sunqi@example.com', 20),
    ('周八', 'zhouba@example.com', 24),
    ('吴九', 'wujiu@example.com', 19),
    ('郑十', 'zhengshi@example.com', 22);

INSERT INTO courses (student_id, course_name, score) VALUES
    (1, '数据库原理', 85.5),
    (1, '操作系统', 90.0),
    (1, '数据结构', 88.0),
    (2, '数据库原理', 78.0),
    (2, '数据结构', 92.5),
    (3, '操作系统', 88.0),
    (3, '数据结构', 76.0),
    (4, '数据库原理', 95.0),
    (4, '操作系统', 87.5),
    (5, '操作系统', 82.5),
    (5, '数据库原理', 79.0),
    (6, '数据结构', 91.0),
    (7, '数据库原理', 68.5),
    (7, '操作系统', 72.0),
    (8, '数据结构', 86.0),
    (8, '数据库原理', 83.0);

INSERT INTO accounts (name, balance) VALUES
    ('小明', 1000.00),
    ('小红', 500.00),
    ('小李', 2000.00);

INSERT INTO events (event_type, data) VALUES
    ('click', '{"page": "/home", "button": "signup", "duration": 3.5}'),
    ('click', '{"page": "/pricing", "button": "buy", "duration": 1.2}'),
    ('pageview', '{"page": "/home", "referrer": "google.com"}'),
    ('pageview', '{"page": "/docs", "referrer": "github.com"}'),
    ('error', '{"code": 500, "message": "Internal Server Error", "stack": ["app.js:12", "router.js:45"]}');

-- ============================================
-- 创建常用索引
-- ============================================
CREATE INDEX idx_students_name ON students(name);
CREATE INDEX idx_courses_student_id ON courses(student_id);
CREATE INDEX idx_courses_name ON courses(course_name);
CREATE INDEX idx_events_data ON events USING GIN (data);

-- ============================================
-- 验证数据
-- ============================================
SELECT '学生数: ' || count(*) FROM students;
SELECT '选课数: ' || count(*) FROM courses;
SELECT '账户数: ' || count(*) FROM accounts;
SELECT '事件数: ' || count(*) FROM events;

将以上脚本保存为 init_school.sql,然后执行:

bash
createdb -U postgres school
psql -U postgres -d school -f init_school.sql

即可一键搭建完整的练习环境。


祝你学习顺利!建议配合实际操作练习,每章花 30~60 分钟动手敲 SQL,比纯看文档效果好 10 倍。

坚持是一种品格