sql >> Databasteknik >  >> RDS >> Mysql

MySQL:Förstå mappningstabeller

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)


  1. xampp MySQL startar inte

  2. Hur man ställer in asynkron replikering mellan MariaDB Galera-kluster

  3. Hur undkommer man strängar i SQL Server med PHP?

  4. Massinsättning i MYSQL från XML-filer