Mysql
 sql >> Base de données >  >> RDS >> Mysql

MySQL :comprendre les tables de mappage

Lors de l'utilisation de relations plusieurs-à-plusieurs, la seule façon réaliste de gérer cela est d'utiliser une table de mappage.

Disons que nous avons une école avec des enseignants et des élèves, un élève peut avoir plusieurs enseignants et vice versa.

Donc on fait 3 tableaux

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 table des étudiants aura 1000 enregistrements
La table des enseignants aura 20 enregistrements
La table link_st aura autant d'enregistrements qu'il y a de liens (PAS 20x1000, mais seulement pour les liens réels).

Sélection
Vous sélectionnez par ex. élèves par enseignant utilisant :

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

Normalement, vous devez toujours utiliser une inner join ici.

Faire un lien
Lorsque vous affectez un enseignant à un élève (ou vice versa, c'est la même chose) .Vous n'avez qu'à faire :

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'

C'est un peu une mauvaise utilisation d'une jointure interne, mais cela fonctionne tant que les noms sont uniques.
Si vous connaissez les identifiants, vous pouvez simplement les insérer directement bien sûr.
Si les noms sont pas unique ce sera un échec et ne doit pas être utilisé.

Comment éviter les liens en double
Il est très important d'éviter les liens en double, toutes sortes de mauvaises choses se produiront si vous en avez.
Si vous voulez empêcher l'insertion de liens en double dans votre table de liens, vous pouvez déclarer un unique index sur le lien (recommandé)

ALTER TABLE link_st
  ADD UNIQUE INDEX s_t (student_id, teacher_id); 

Ou vous pouvez faire la vérification dans l'instruction d'insertion (pas vraiment recommandé, mais ça marche).

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)

Cela ne sélectionnera que 548, 785 si ces données ne sont pas déjà dans le link_st table, et ne renverra rien si ces données sont déjà dans link_st. Il refusera donc d'insérer des valeurs en double.

Si vous avez une table d'écoles, cela dépend si un élève peut être inscrit dans plusieurs écoles (peu probable, mais supposons) et si les enseignants peuvent être inscrits dans plusieurs écoles. Très possible.

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

Vous pouvez répertorier tous les élèves d'une école comme suit :

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)