Когато използвате релации много към много, единственият реалистичен начин да се справите с това е с таблица за съпоставяне.
Да приемем, че имаме училище с учители и ученици, един ученик може да има няколко учители и обратно.
Така правим 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) <--- first link student to the link-table
INNER JOIN teacher t ON (l.teacher_id = t.id) <--- then link teacher to the link table.
ORDER BY t.id, s.id
Обикновено винаги трябва да използвате вътрешно присъединяване
тук.
Създаване на връзка
Когато назначавате учител на ученик (или обратното, това е същото) .Трябва да направите само:
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'
Това е малко злоупотреба с вътрешно присъединяване, но работи, стига имената да са уникални.
Ако знаете идентификаторите, можете просто да ги вмъкнете директно, разбира се.
Ако имената са не е уникално, това ще е неуспех и не трябва да се използва.
Как да избегнем дублиращи се връзки
Много е важно да избягвате дублиращи се връзки, ще се случат всякакви лоши неща, ако имате такива.
Ако искате да предотвратите вмъкването на дублиращи се връзки във вашата таблица с връзки, можете да декларирате уникаленкод> индекс на връзката (препоръчително)
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)
Това ще избере само 548, 785 if тези данни вече не са в link_st
таблица и няма да върне нищо, ако тези данни вече са във link_st. Така че ще откаже да вмъкне дублиращи се стойности.
Ако имате настолни училища, зависи дали един ученик може да бъде записан в няколко училища (малко вероятно, но нека предположим) и учителите могат да бъдат записани в няколко училища. Много възможно.
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)