数据库设计——当学生记录本身也需要相互关联时,我们应该如何设计teacher/student关系
Database design - How should we design a teacher/student relationship when student records themselves also need to be associated to each other
所以这是我们一直在努力尝试找出优化方法的东西。
在一个简单的世界中,这可以通过一个简单的多对多桥接 table 来解决,如下所示:
teachers_students_mappings
id
teacher_id
student_id
1
1
1
2
1
2
3
1
3
4
2
1
然而,我们还有另一个复杂的问题需要解决。学生记录可以来自不同的“来源”,即:
- 该学生是由另一个系统创建的,该系统将该学生及其 类 的记录传输给我们(大多数学生和师生关系记录都是通过这种方式创建的)。
- 学生自行注册(通过应用程序),或
- 该学生由教师手动创建(通过教师门户)
因此,在某些情况下,来自不同来源的学生记录也应该相互关联:
students
id
name
id_number
source_type
1
Rachel Doe
9898123
created_by_system
2
Rachel Doe
9898123
app_user
3
John Doe
9833456
created_by_teacher
例如上面,我们有一个案例,其中 student_ids 1 和 2,Rachel Doe,实际上是同一个人。第一条记录由系统自动生成,第二条记录是 Rachel 在她的学生应用程序上在系统中注册时创建的。两条记录共享一个 id_number
,这是学校的唯一标识符。
如果我们这样做 student_ids 1 和 2 都链接到 Rachel 的所有老师,她的老师会看到重复的记录,即 Rachel 的应用程序帐户和她由系统创建的记录。因此,将这两个 student_id
记录相互关联起来似乎更明智,但这将如何影响 teachers_students_mappings
table?
理论上也有可能同一个学生存在3条不同的学生记录(即老师手动创建记录,然后系统创建记录,然后学生在应用程序上创建帐户)。
在输入新记录的数据之前,您必须检查 id_number 是否存在。在那种情况下,您必须 return 标识而不是插入该记录。
因为您已经拥有一个独一无二的 id_number
,并提供了一种机制来实现您拥有 一个,而不是 两个 Rachel 做的,用它作为 Students
table 的 PRIMARY KEY
。 不每个学生还有另一个id
。
另一方面,如果您有一个 StudentHistory
table 来记录每个学生或为每个学生采取的各种行动,则它需要自己的 PRIMARY KEY
。这似乎是一个单独的话题。
因此,在为学生“插入”或“更新”一行时,请使用
INSERT INTO Students (id_number, name, foo, ...)
VALUES ("9898123", "Rachel Doe", 123, ...)
ON DUPLICATE KEY UPDATE
foo = VALUES(foo), ...;
或者(如果来自 SELECT
):
INSERT INTO Students (id_number, name, foo, ...)
SELECT id_number, name, foo, ...
FROM other table ...
ON DUPLICATE KEY UPDATE
foo = VALUES(foo), ...;
所以这是我们一直在努力尝试找出优化方法的东西。
在一个简单的世界中,这可以通过一个简单的多对多桥接 table 来解决,如下所示:
teachers_students_mappings
id | teacher_id | student_id |
---|---|---|
1 | 1 | 1 |
2 | 1 | 2 |
3 | 1 | 3 |
4 | 2 | 1 |
然而,我们还有另一个复杂的问题需要解决。学生记录可以来自不同的“来源”,即:
- 该学生是由另一个系统创建的,该系统将该学生及其 类 的记录传输给我们(大多数学生和师生关系记录都是通过这种方式创建的)。
- 学生自行注册(通过应用程序),或
- 该学生由教师手动创建(通过教师门户)
因此,在某些情况下,来自不同来源的学生记录也应该相互关联:
students
id | name | id_number | source_type |
---|---|---|---|
1 | Rachel Doe | 9898123 | created_by_system |
2 | Rachel Doe | 9898123 | app_user |
3 | John Doe | 9833456 | created_by_teacher |
例如上面,我们有一个案例,其中 student_ids 1 和 2,Rachel Doe,实际上是同一个人。第一条记录由系统自动生成,第二条记录是 Rachel 在她的学生应用程序上在系统中注册时创建的。两条记录共享一个 id_number
,这是学校的唯一标识符。
如果我们这样做 student_ids 1 和 2 都链接到 Rachel 的所有老师,她的老师会看到重复的记录,即 Rachel 的应用程序帐户和她由系统创建的记录。因此,将这两个 student_id
记录相互关联起来似乎更明智,但这将如何影响 teachers_students_mappings
table?
理论上也有可能同一个学生存在3条不同的学生记录(即老师手动创建记录,然后系统创建记录,然后学生在应用程序上创建帐户)。
在输入新记录的数据之前,您必须检查 id_number 是否存在。在那种情况下,您必须 return 标识而不是插入该记录。
因为您已经拥有一个独一无二的 id_number
,并提供了一种机制来实现您拥有 一个,而不是 两个 Rachel 做的,用它作为 Students
table 的 PRIMARY KEY
。 不每个学生还有另一个id
。
另一方面,如果您有一个 StudentHistory
table 来记录每个学生或为每个学生采取的各种行动,则它需要自己的 PRIMARY KEY
。这似乎是一个单独的话题。
因此,在为学生“插入”或“更新”一行时,请使用
INSERT INTO Students (id_number, name, foo, ...)
VALUES ("9898123", "Rachel Doe", 123, ...)
ON DUPLICATE KEY UPDATE
foo = VALUES(foo), ...;
或者(如果来自 SELECT
):
INSERT INTO Students (id_number, name, foo, ...)
SELECT id_number, name, foo, ...
FROM other table ...
ON DUPLICATE KEY UPDATE
foo = VALUES(foo), ...;