数据库入门:SQL 基础与关系代数
本文最后更新于 22 天前,如有失效请评论区留言。

最近在整理数据库相关知识,发现 SQL 和关系代数这两个东西其实是同一枚硬币的两面。关系代数给你理论基础,SQL 给你实践工具。这篇文章就来聊聊这两个核心概念,算是我学习数据库的一份笔记。

什么是关系模型?

在聊 SQL 之前,我们先搞清楚关系模型(Relational Model)。这是 E.F. Codd 在 1970 年提出的,核心思想其实很简单:用表(Table)来表示数据。

一张表由几个关键部分组成:

  • Relation(关系):就是一张表
  • Tuple(元组):表中的一行,代表一条记录
  • Attribute(属性):表中的一列,代表一个字段
  • Schema(模式):表的结构定义,包括列名和数据类型
  • Primary Key(主键):唯一标识一行的属性或属性组合
  • Foreign Key(外键):引用其他表主键的属性,用于建立表之间的关联

举个例子,假设我们有一个学生选课系统,核心表结构如下:

Students (student_id PK, name, major, enrollment_year)
Courses  (course_id PK, course_name, credits, department)
Enrollments (enrollment_id PK, student_id FK, course_id FK, grade, semester)

这里 Enrollments 就是一张关联表(Junction Table),通过外键把 Students 和 Courses 联系起来。这种设计体现了关系模型的精髓——数据之间通过外键约束建立联系,而不是把所有信息塞进一张大表。

关系代数:SQL 背后的数学

关系代数(Relational Algebra)是一套形式化的查询语言,是 SQL 的理论基础。它定义了对关系(表)进行操作的一组基本运算。理解关系代数,能帮你更好地理解 SQL 查询到底在干什么。

基本运算

关系代数有 6 种基本运算,其他运算都可以由它们组合而成:

1. 选择(Selection, σ)——按条件筛选行,对应 SQL 的 WHERE。

σ_{major=’CS’}(Students) 表示”从 Students 表中选出 CS 专业的学生”。SQL 里就是:

SELECT * FROM Students WHERE major = 'CS';

2. 投影(Projection, π)——选择特定的列,对应 SQL 的 SELECT 列名。

π_{name, major}(Students) 表示”只看 Students 的 name 和 major 列”:

SELECT name, major FROM Students;

3. 并(Union, ∪)——两个关系的合并,对应 SQL 的 UNION。

4. 差(Difference, −)——从一个关系中减去另一个关系中存在的元组,对应 SQL 的 EXCEPT。

5. 笛卡尔积(Cartesian Product, ×)——两个关系的所有可能组合,对应 SQL 的 CROSS JOIN。

6. 重命名(Rename, ρ)——给关系或属性换个名字,对应 SQL 的 AS。

派生运算

基于上面 6 个基本运算,我们可以构造出更强大的操作:

交(Intersection, ∩):两个关系的公共部分。R ∩ S = R − (R − S)。SQL 里直接用 INTERSECT。

连接(Join, ⋈):这可能是最常用的操作了。笛卡尔积 + 选择 = 连接。SQL 里的 JOIN 就是这个意思:

-- 自然连接(Natural Join):自动匹配同名属性
SELECT s.name, c.course_name, e.grade
FROM Students s
JOIN Enrollments e ON s.student_id = e.student_id
JOIN Courses c ON e.course_id = c.course_id;

除(Division, ÷):这个稍微抽象一点。它回答的是”哪些 X 与所有 Y 都有关联”这类问题。比如”选了所有 CS 课程的学生”:

-- 用 SQL 实现除法(没有直接的 DIVIDE 运算符)
SELECT DISTINCT s.name
FROM Students s
WHERE NOT EXISTS (
    SELECT c.course_id FROM Courses c
    WHERE c.department = 'CS'
    AND NOT EXISTS (
        SELECT e.enrollment_id FROM Enrollments e
        WHERE e.student_id = s.student_id
        AND e.course_id = c.course_id
    )
);

💡 Tips:关系代数的除法在 SQL 中没有直接的运算符,通常用双重 NOT EXISTS 来实现。这是面试中常见的考点!

SQL CRUD:日常操作四件套

了解了关系代数,我们来看看 SQL 的实际操作。CRUD 是 Create、Read、Update、Delete 的缩写,基本上你和数据库打交道 90% 的时间都在做这四件事。

Create —— 插入数据

-- 插入单条记录
INSERT INTO Students (student_id, name, major, enrollment_year)
VALUES (1, 'Alice', 'CS', 2023);

-- 批量插入
INSERT INTO Students (student_id, name, major, enrollment_year)
VALUES 
    (2, 'Bob', 'Math', 2023),
    (3, 'Charlie', 'CS', 2024),
    (4, 'Diana', 'Physics', 2022);

Read —— 查询数据

查询是 SQL 中最复杂的部分,也是关系代数的核心应用。来几个常用的例子:

-- 基础查询 + 条件筛选(σ 选择)
SELECT name, major FROM Students
WHERE enrollment_year >= 2023
ORDER BY name ASC;

-- 聚合查询
SELECT major, COUNT(*) AS student_count, AVG(enrollment_year) AS avg_year
FROM Students
GROUP BY major
HAVING COUNT(*) > 1;

-- 子查询:找出选了 'Database Systems' 这门课的学生
SELECT name FROM Students
WHERE student_id IN (
    SELECT student_id FROM Enrollments
    WHERE course_id = (
        SELECT course_id FROM Courses
        WHERE course_name = 'Database Systems'
    )
);

Update & Delete

-- 更新:给 Alice 改专业
UPDATE Students SET major = 'Data Science'
WHERE student_id = 1;

-- 删除:移除成绩为 F 的选课记录
DELETE FROM Enrollments
WHERE grade = 'F';

⚠️ 警告:UPDATE 和 DELETE 不带 WHERE 条件的话会影响全表!生产环境一定要小心,建议先用 SELECT 确认影响范围。

JOIN 深入:连接的几种类型

JOIN 是 SQL 中最重要的操作之一,对应关系代数中的连接运算。常见的几种类型:

-- INNER JOIN:只返回两边都匹配的行
SELECT s.name, e.grade
FROM Students s
INNER JOIN Enrollments e ON s.student_id = e.student_id;

-- LEFT JOIN:左表全部保留,右表没有匹配的填 NULL
SELECT s.name, e.grade
FROM Students s
LEFT JOIN Enrollments e ON s.student_id = e.student_id;

-- 自连接:和自己连,比如找同专业的学生对
SELECT a.name AS student1, b.name AS student2
FROM Students a
JOIN Students b ON a.major = b.major AND a.student_id < b.student_id;

理解 JOIN 的关键在于想象两个集合的韦恩图(Venn Diagram):INNER JOIN 取交集,LEFT JOIN 取左集全集加交集,RIGHT JOIN 反之,FULL OUTER JOIN 取全集。

关系代数与 SQL 的对应关系

最后来个总结,把关系代数和 SQL 的对应关系理清楚:

  • σ 选择 → WHERE 子句
  • π 投影 → SELECT 列名
  • ∪ 并 → UNION
  • − 差 → EXCEPT
  • × 笛卡尔积 → CROSS JOIN
  • ⋈ 连接 → JOIN (INNER/LEFT/RIGHT)
  • ÷ 除法 → 双重 NOT EXISTS
  • ρ 重命名 → AS

搞清楚这个映射关系,你就能从理论层面理解 SQL 查询在做什么,写复杂查询的时候也会更有思路。

一些实用技巧

最后分享几个实战中的小技巧:

  • EXPLAIN:用 EXPLAIN 查看查询执行计划,了解数据库如何优化你的查询
  • Index:在经常用于 WHERE、JOIN、ORDER BY 的列上建索引,能显著提升查询速度
  • 避免 SELECT *:只选需要的列,减少数据传输量
  • CTE(Common Table Expression):用 WITH 子句把复杂查询拆分成可读的步骤
  • 事务(Transaction):多条相关操作用 BEGIN/COMMIT/ROLLBACK 包裹,保证数据一致性
-- CTE 示例:找出每个专业成绩最好的学生
WITH RankedStudents AS (
    SELECT s.name, s.major, e.grade,
           RANK() OVER (PARTITION BY s.major ORDER BY e.grade DESC) AS rnk
    FROM Students s
    JOIN Enrollments e ON s.student_id = e.student_id
)
SELECT name, major, grade FROM RankedStudents WHERE rnk = 1;

好了,这篇笔记就到这里。SQL 和关系代数是数据库的基石,掌握了它们,后面学习索引优化、事务处理、分布式数据库等内容就有了扎实的基础。如果你也在学数据库,希望这篇文章对你有帮助!

版权声明:除特殊说明,博客文章均为原创,依据CC BY-SA 4.0许可证进行授权,转载请附上出处链接及本声明。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇