多対多の関係を使用する場合、これを処理する唯一の現実的な方法は、マッピングテーブルを使用することです。
教師と生徒がいる学校があるとしましょう。生徒は複数の教師を持つことができ、その逆も可能です。
したがって、3つのテーブルを作成します
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)
Studentテーブルには1000レコードがあります
Teacherテーブルには20レコードがあります
link_stテーブルにはリンクと同じ数のレコードがあります(20x1000ではなく、実際のリンクのみ)。
選択
たとえば、使用する教師ごとの生徒:
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
通常は、常に内部結合
を使用する必要があります ここ。
リンクを作成する
教師を生徒に割り当てる場合(またはその逆の場合も同様です) 。あなたがする必要があるのは:
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'
これは内部結合の誤用ですが、名前が一意である限り機能します。
IDがわかっている場合は、もちろん直接挿入できます。
名前がユニークではありませんが、これは失敗になります 使用しないでください。
重複リンクを回避する方法
重複リンクを回避することは非常に重要です。重複リンクがあると、あらゆる種類の悪いことが起こります。
リンクテーブルへの重複リンクの挿入を防ぎたい場合は、unique<を宣言できます。 / code> リンクのインデックス(推奨)
ALTER TABLE link_st
ADD UNIQUE INDEX s_t (student_id, teacher_id);
または、insertステートメントでチェックを行うこともできます(実際には推奨されませんが、機能します)。
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)
これは、 if の場合にのみ548、785を選択します そのデータはまだlink_st
にありません テーブルであり、そのデータがすでにlink_stにある場合は、何も返しません。したがって、重複する値の挿入は拒否されます。
テーブルスクールがある場合は、生徒が複数の学校に登録できるかどうか(可能性は低いですが、想定できます)と教師が複数の学校に登録できるかどうかによって異なります。非常に可能です。
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
次のように、学校のすべての生徒を一覧表示できます。
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)