Podczas korzystania z relacji wiele-do-wielu jedynym realistycznym sposobem radzenia sobie z tym jest użycie tabeli mapowania.
Powiedzmy, że mamy szkołę z nauczycielami i uczniami, uczeń może mieć wielu nauczycieli i odwrotnie.
Więc robimy 3 stoły
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)
Tabela uczniów będzie miała 1000 rekordów
Tabela nauczyciela będzie miała 20 rekordów
Tabela link_st będzie zawierać tyle rekordów, ile jest linków (NIE 20x1000, ale tylko dla rzeczywistych linków).
Wybór
Wybierasz m.in. uczniów na nauczyciela przy użyciu:
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
Zwykle zawsze powinieneś używać połączenia wewnętrznego
tutaj.
Tworzenie linku
Gdy przypiszesz nauczyciela do ucznia (lub odwrotnie, to samo) .Wystarczy tylko:
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'
Jest to trochę niewłaściwe użycie wewnętrznego sprzężenia, ale działa tak długo, jak nazwy są unikalne.
Jeśli znasz identyfikatory, możesz po prostu wstawić je bezpośrednio.
Jeśli nazwy są nie wyjątkowy to będzie porażka i nie powinny być używane.
Jak uniknąć duplikatów linków
Bardzo ważne jest unikanie duplikatów linków, jeśli je posiadasz, mogą się zdarzyć różne złe rzeczy.
Jeśli chcesz zapobiec wstawianiu zduplikowanych linków do tabeli linków, możesz zadeklarować unikalny indeks na linku (zalecane)
ALTER TABLE link_st
ADD UNIQUE INDEX s_t (student_id, teacher_id);
Możesz też sprawdzić w instrukcji insert (niezalecane, ale działa).
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)
Spowoduje to wybranie tylko 548, 785 jeśli że dane nie znajdują się jeszcze w link_st
table i nic nie zwróci, jeśli te dane są już w link_st. Więc odmówi wstawienia zduplikowanych wartości.
Jeśli masz szkoły stołowe, zależy to od tego, czy uczeń może być zapisany do wielu szkół (mało prawdopodobne, ale załóżmy), a nauczyciele mogą być zapisani do wielu szkół. Bardzo możliwe.
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
Możesz wymienić wszystkich uczniów w szkole w następujący sposób:
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)