使用多对多关系时,处理的唯一现实方法是使用映射表。
假设我们有一个带有教师和学生的学校,一个学生可以有多个老师,反之亦然。
因此,我们创建了3个表:
student
id unsigned integer auto_increment primary key
name varchar
teacher
id unsigned integer auto_increment primary key
name varchar
link_st
student_id integer not null
teacher_id integer not null
primary key (student_id, teacher_id)
学生表将有1000条记录
教师表将有20条记录
link_st表将有与链接数量相同的记录(不是20x1000,只有实际链接数量)。
选择
您可以使用以下方式选择例如每个老师的学生:
SELECT s.name, t.name
FROM student
INNER JOIN link_st l ON (l.student_id = s.id) <
INNER JOIN teacher t ON (l.teacher_id = t.id) <
ORDER BY t.id, s.id
通常在这种情况下应该始终使用内连接inner join
。
创建链接
当你要将老师分配给学生(或者反过来,都一样)时,只需要执行以下操作:
INSERT INTO link_st (student_id, teacher_id)
SELECT s.id, t.id
FROM student s
INNER JOIN teacher t ON (t.name = 'Jones')
WHERE s.name = 'kiddo'
这有点滥用内联连接,但只要名称唯一,它就可以工作。
当然,如果您知道id,您也可以直接插入它们。
如果名称不唯一,则会失败,不应使用。
如何避免重复链接
避免重复链接非常重要,如果出现这种情况,将会发生各种糟糕的事情。
如果您想防止将重复链接插入到链接表中,可以在链接上声明一个
unique
索引(建议)。
ALTER TABLE link_st
ADD UNIQUE INDEX s_t (student_id, teacher_id);
或者您可以在插入语句中进行检查(虽然不是很推荐,但它确实有效)。
INSERT INTO link_st (student_id, teacher_id)
SELECT s.id, t.id
FROM student s
INNER JOIN teacher t ON (t.id = 548)
LEFT JOIN link_st l ON (l.student_id = s.id AND l.teacher_id = t.id)
WHERE (s.id = 785) AND (l.id IS NULL)
如果数据已经存在于link_st
表中,则此操作仅会选择548,785条数据,否则将不会选择任何数据,并且拒绝插入重复值。
如果您有一个名为schools的表,那么这取决于学生是否可以在多所学校注册(不太可能,但让我们假设),而教师可以在多所学校注册。这是非常可能的。
table school
id unsigned integer auto_increment primary key
name varchar
table school_members
id id unsigned integer auto_increment primary key
school_id integer not null
member_id integer not null
is_student boolean not null
您可以像这样列出学校中的所有学生:
SELECT s.name
FROM school i
INNER JOIN school_members m ON (i.id = m.school_id)
INNER JOIN student s ON (s.id = m.member_id AND m.is_student = true)
l.student_id
而不是link_st.student_id
。 - phant0mlink
的表取别名呢? - Johanl
本身就是一个失败吧。 - Johan