När man använder många-till-många-relationer är det enda realistiska sättet att hantera detta med en mappningstabell.
Låt oss säga att vi har en skola med lärare och elever, en elev kan ha flera lärare och tvärtom.
Så vi gör 3 bord
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)
Elevtabellen kommer att ha 1000 poster
Lärartabellen kommer att ha 20 poster
Link_st-tabellen kommer att ha lika många poster som det finns länkar (INTE 20x1000, utan bara för själva länkarna).
Urval
Du väljer t.ex. elever per lärare med:
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
Normalt ska du alltid använda en inner join
här.
Göra en länk
När du tilldelar en lärare till en elev (eller tvärtom, det är samma sak) .Du behöver bara göra:
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'
Det här är lite missbruk av en inre sammanfogning, men det fungerar så länge namnen är unika.
Om du känner till id:n kan du naturligtvis bara infoga dem direkt.
Om namnen är inte unikt detta kommer att vara ett misslyckande och bör inte användas.
Så undviker du dubbletter av länkar
Det är mycket viktigt att undvika dubbletter av länkar, alla möjliga dåliga saker kommer att hända om du har sådana.
Om du vill förhindra att du infogar dubbletter av länkar till din länktabell kan du deklarera en unik index på länken (rekommenderas)
ALTER TABLE link_st
ADD UNIQUE INDEX s_t (student_id, teacher_id);
Eller så kan du göra kontrollen i infoga uttalandet (rekommenderas inte riktigt, men det fungerar).
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)
Detta kommer bara att välja 548, 785 om att data inte redan finns i link_st
tabell, och kommer inte att returnera något om den informationen redan finns i link_st. Så det kommer att vägra att infoga dubbletter av värden.
Om du har en tabell för skolor, beror det på om en elev kan vara inskriven i flera skolor (osannolikt, men låt oss anta) och lärare kan vara inskrivna i flera skolor. Mycket möjligt.
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
Du kan lista alla elever i en skola så här:
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)