Many-to-many relations in RDBMS databases
在像 mySQL 这样的 RDBMS 数据库中处理多对多关系的最佳方法是什么?
已尝试使用数据透视表来跟踪关系,但它会导致以下任一情况:
-
规范化被抛在后面
-
为空或 null
的列
您采取了哪些方法来支持多对多关系?
在专门用于该关系的表(有时称为联结表)中跟踪多对多关系。此表将关系建模为两个指向相反方向的一对多关系。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | CREATE TABLE customer ( customer_id VARCHAR NOT NULL, name VARCHAR NOT NULL, PRIMARY KEY (customer_id)); CREATE TABLE publication ( issn VARCHAR NOT NULL, name VARCHAR NOT NULL, PRIMARY KEY (issn)); -- Many-to-many relationship for subscriptions. CREATE TABLE subscription ( customer_id VARCHAR NOT NULL, FOREIGN KEY customer_id REFERENCES customer (customer_id), issn VARCHAR NOT NULL, FOREIGN KEY issn REFERENCES publication (issn), BEGIN TIMESTAMP NOT NULL, PRIMARY KEY (customer_id, issn)); |
然后,您可以使用联结表通过外键连接其他表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | -- Which customers subscribe to publications named 'Your Garden Gnome'? SELECT customer.* FROM customer JOIN subscription ON subscription.customer_id = customer.customer_id JOIN publication ON subscription.issn = publication.issn WHERE publication.name = 'Your Garden Gnome'; -- Which publications do customers named 'Fred Nurk' subscribe to? SELECT publication.* FROM publication JOIN subscription ON subscription.issn = publication.issn JOIN customer ON subscription.customer_id = customer.customer_id WHERE customer.name = 'Fred Nurk'; |
我会使用数据透视表,但我看不出您的问题来自哪里。使用一个简单的学生/班级示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Student ------- Id (PRIMARY KEY) FirstName LastName Course ------ Id (PRIMARY KEY) Title StudentCourse ------------- StudentId (FOREIGN KEY -> Student) CourseId (FOREIGN KEY -> Course) |
或者,正如其他人在回答您的学生/教师/课程问题时提到的那样(这将有一个额外的表格来存储课程中的人员类型):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | PersonType ---------- Id (PRIMARY KEY) TYPE Person ------ Id (PRIMARY KEY) FirstName LastName TYPE (FOREIGN KEY -> PersonType) Course ------ Id (PRIMARY KEY) Title PersonCourse ------------ PersonId (FOREIGN KEY -> Person) CourseId (FOREIGN KEY -> Course) |
Student 表包含学生信息,Course 表存储课程信息……而数据透视表仅包含相关学生和课程的 ID。这不应该导致任何空/空列或任何东西。
除了贾斯汀的回答:如果您巧妙地使用外键约束,您可以控制数据更新或删除时发生的情况。这样,您就可以确保您不会得到非规范化的数据。