Quando si utilizzano relazioni molti-a-molti, l'unico modo realistico per gestirlo è con una tabella di mappatura.
Diciamo che abbiamo una scuola con insegnanti e studenti, uno studente può avere più insegnanti e viceversa.
Quindi creiamo 3 tabelle
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)
La tabella studenti avrà 1000 record
La tabella insegnanti avrà 20 record
La tabella link_st avrà tanti record quanti sono i collegamenti (NON 20x1000, ma solo per i collegamenti effettivi).
Selezione
Selezioni ad es. studenti per insegnante utilizzando:
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
Normalmente dovresti sempre usare un inner join
qui.
Creare un collegamento
Quando assegni un insegnante a uno studente (o viceversa, è lo stesso) .Devi solo fare:
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'
Questo è un po' un uso improprio di un inner join, ma funziona purché i nomi siano univoci.
Se conosci gli ID, puoi inserirli direttamente ovviamente.
Se i nomi sono non univoco, questo sarà un errore e non dovrebbe essere usato.
Come evitare link duplicati
È molto importante evitare link duplicati, se li hai accadranno ogni sorta di brutte cose.
Se vuoi evitare di inserire link duplicati nella tabella dei link, puoi dichiarare un unique
indice sul link (consigliato)
ALTER TABLE link_st
ADD UNIQUE INDEX s_t (student_id, teacher_id);
Oppure puoi fare il controllo nella dichiarazione di inserimento (non consigliato, ma funziona).
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)
Questo selezionerà solo 548, 785 se quei dati non sono già nel link_st
tabella e non restituirà nulla se quei dati sono già in link_st. Quindi rifiuterà di inserire valori duplicati.
Se hai un tavolo scuole, dipende se uno studente può essere iscritto a più scuole (improbabile, ma supponiamo) e gli insegnanti possono essere iscritti a più scuole. Molto possibile.
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
Puoi elencare tutti gli studenti di una scuola in questo modo:
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)