CodeGym /课程 /SQL SELF /创建表 enrollments 用于关联学生和课程

创建表 enrollments 用于关联学生和课程

SQL SELF
第 20 级 , 课程 1
可用

再啰嗦一下哈。我们也来详细过一遍怎么一步步搞定 MANY-TO-MANY 结构。准备好了吗?

MANY-TO-MANY 关系在学生和课程之间,没法直接用一张表搞定。一个学生可以报好几个课程,一个课程也可以被好几个学生选。

为了解决这个问题,我们建一个中间表 enrollments,用来存报名信息,也就是哪对学生-课程是存在的。这样不仅能保证数据完整性,还能很方便地扩展功能,比如加个报名日期啥的。

enrollments 表长啥样?

你已经知道,enrollments 表是 studentscourses 两张表之间的核心连接点。结构如下:

CREATE TABLE enrollments (
    enrollment_id SERIAL PRIMARY KEY,           -- 唯一ID记录
    student_id INT REFERENCES students(student_id), -- 指向 students 表的外键
    course_id INT REFERENCES courses(course_id),    -- 指向 courses 表的外键
    enrollment_date DATE DEFAULT CURRENT_DATE   -- 学生报名课程的日期
);

来拆解一下每一行:

  • enrollment_id:这是每条记录的唯一标识。每个报名课程的学生都得有唯一ID。
  • student_id:表示哪个学生报名了。这是个外键,指向 students 表(student_id 列)。
  • course_id:表示学生报了哪个课程。这个字段关联 courses 表(course_id 列)。
  • enrollment_date:很实用的补充,显示报名日期。我们用 DEFAULT CURRENT_DATE,这样插入记录时会自动写上当天日期。

创建 studentscourses

在继续之前,先确保我们已经有 studentscourses 这两张表:

CREATE TABLE students (
    student_id SERIAL PRIMARY KEY,      -- 学生唯一标识
    name TEXT NOT NULL,                 -- 学生姓名
    email TEXT NOT NULL UNIQUE          -- 学生邮箱,不能重复
);
CREATE TABLE courses (
    course_id SERIAL PRIMARY KEY,       -- 课程唯一标识
    title TEXT NOT NULL,                -- 课程名称
    description TEXT,                   -- 课程描述
    start_date DATE                     -- 课程开始日期
);

注意,这里我们加了一些有用的细节,比如学生邮箱唯一、课程表里有描述字段。

把一切串起来

现在表都准备好了,来建 enrollments 表:

CREATE TABLE enrollments (
    enrollment_id SERIAL PRIMARY KEY,           -- 报名唯一ID
    student_id INT NOT NULL REFERENCES students(student_id), -- 外键
    course_id INT NOT NULL REFERENCES courses(course_id),    -- 外键
    enrollment_date DATE DEFAULT CURRENT_DATE   -- 报名日期
);

往表里插数据

表都建好了,但没数据多无聊。来加点学生、课程和报名记录:

插入学生:

INSERT INTO students (name, email)
VALUES
    ('Alex Lin', 'alex.lin@example.com'),
    ('Maria Chi', 'maria.chi@example.com'),
    ('Otto Song', 'otto.song@example.com');

插入课程:

INSERT INTO courses (title, description, start_date)
VALUES
    ('编程基础', '给初学者的编程课程。', '2023-11-01'),
    ('数据库', '学习 SQL 和关系型数据库。', '2023-11-15'),
    ('Web开发', '做网站和 Web 应用。', '2023-12-01');

插入报名记录:

INSERT INTO enrollments (student_id, course_id)
VALUES
    (1, 1), -- Alex Lin 报了“编程基础”
    (1, 2), -- Alex Lin 报了“数据库”
    (2, 2), -- Maria Chi 报了“数据库”
    (3, 3); -- Otto Song 报了“Web开发”

这里 student_idcourse_id 跟对应表里的ID一致。

用查询检查关联

查所有报名:

SELECT e.enrollment_id, s.name AS student_name, c.title AS course_title, e.enrollment_date
FROM enrollments e
JOIN students s ON e.student_id = s.student_id
JOIN courses c ON e.course_id = c.course_id;

结果:

enrollment_id student_name course_title enrollment_date
1 Alex Lin 编程基础 2023-11-01
2 Alex Lin 数据库 2023-11-01
3 Maria Chi 数据库 2023-11-01
4 Otto Song Web开发 2023-11-01

动手练习题

你可以再加几个学生和课程,然后把他们报名到 enrollments 表里。比如加个课程“机器学习”,让1-2个学生报名。用上面的查询查查结果。

常见的坑

用外键和中间表时有几个常见的坑,大家经常踩:

  1. 父表里没记录: 如果你往 enrollmentsstudent_idcourse_id,但 studentscourses 表里没有对应的ID,就会报错。外键会死死盯着这个。

  2. 删数据导致数据不完整: 如果你删了某个学生或课程,而他们还在 enrollments 表里被用着,又没设置 ON DELETE CASCADE,也会报错。

  3. 重复记录: 注意别让同一个学生重复报名同一个课程,除非业务逻辑允许。

现在你已经有了一个能用的模型,来表示 PostgreSQL 里学生和课程的 MANY-TO-MANY 关系。这种结构在实际项目里超常见,比如学习管理系统、CRM 等等。冲下节课吧!

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION