如何在设计表时实现一对一,一对多和多对多关系?

时间:2011-09-04 01:17:37

标签: sql oracle database-design

在设计包含一些示例的表时,有没有人可以解释如何实现一对一,一对多和多对多的关系?

4 个答案:

答案 0 :(得分:370)

一对一:使用引用表的外键:

student: student_id, first_name, last_name, address_id
address: address_id, address, city, zipcode, student_id # you can have a
                                                        # "link back" if you need

您还必须在外键列(addess.student_id)上放置一个唯一约束,以防止子表(address)中的多行与引用表中的同一行相关联({{ 1}})。

一对多:在关系的许多方面使用外键链接回“一”方:

student

多对多:使用联结表(example):

teachers: teacher_id, first_name, last_name # the "one" side
classes:  class_id, class_name, teacher_id  # the "many" side

示例查询:

student: student_id, first_name, last_name
classes: class_id, name, teacher_id
student_classes: class_id, student_id     # the junction table

答案 1 :(得分:43)

以下是一些关系类型的真实示例:

<强> 1:1

当且仅当表A中的一条记录与a相关时,关系才是一对一的 表B中最多只有一条记录。

要建立一对一关系,表B的主键(没有孤立记录)必须是表A的辅助键(带有孤立记录)。

例如:

CREATE TABLE Gov(
    GID number(6) PRIMARY KEY, 
    Name varchar2(25), 
    Address varchar2(30), 
    TermBegin date,
    TermEnd date
); 

CREATE TABLE State(
    SID number(3) PRIMARY KEY,
    StateName varchar2(15),
    Population number(10),
    SGID Number(4) REFERENCES Gov(GID), 
    CONSTRAINT GOV_SDID UNIQUE (SGID)
);

INSERT INTO gov(GID, Name, Address, TermBegin) 
values(110, 'Bob', '123 Any St', '1-Jan-2009');

INSERT INTO STATE values(111, 'Virginia', 2000000, 110);

<强> 1:M

当且仅当表A中的一条记录为时,关系才是一对多 与表B中的一个或多个记录相关。但是,表B中的一条记录与表A中的一条记录无关。

要建立一对多关系,表A的主键(“一”表)必须是表B的二级键(“多”表)。

例如:

CREATE TABLE Vendor(
    VendorNumber number(4) PRIMARY KEY,
    Name varchar2(20),
    Address varchar2(20),
    City varchar2(15),
    Street varchar2(2),
    ZipCode varchar2(10),
    Contact varchar2(16),
    PhoneNumber varchar2(12),
    Status varchar2(8),
    StampDate date
);

CREATE TABLE Inventory(
    Item varchar2(6) PRIMARY KEY,
    Description varchar2(30),
    CurrentQuantity number(4) NOT NULL,
    VendorNumber number(2) REFERENCES Vendor(VendorNumber),
    ReorderQuantity number(3) NOT NULL
);

<强> M:N

当且仅当表A中的一条记录与表B中的一条或多条记录相关时,关系才是多对多的。

要建立多对多关系,请创建名为“ClassStudentRelation”的第三个表 它将具有表A和表B的主键。

CREATE TABLE Class(
    ClassID varchar2(10) PRIMARY KEY, 
    Title varchar2(30),
    Instructor varchar2(30), 
    Day varchar2(15), 
    Time varchar2(10)
);

CREATE TABLE Student(
    StudentID varchar2(15) PRIMARY KEY, 
    Name varchar2(35),
    Major varchar2(35), 
    ClassYear varchar2(10), 
    Statusvarchar2(10)
);  

CREATE TABLE ClassStudentRelation(
    StudentID varchar2(15) NOT NULL,
    ClassID varchar2(14) NOT NULL,
    FOREIGN KEY (StudentID) REFERENCES Student(StudentID), 
    FOREIGN KEY (ClassID) REFERENCES Class(ClassID),
    UNIQUE (StudentID, ClassID)
);

答案 2 :(得分:14)

这是一个非常常见的问题,所以我决定将这个答案变成an article

一对多

一对多表关系如下:

One-to-many

在关系数据库系统中,一对多表关系基于子级中的Foreign Key列链接两个表,该列引用父级表行的Primary Key

在上面的表图中,post_id表中的post_comment列与Foreign Key表ID post列具有Primary Key关系:

ALTER TABLE
    post_comment
ADD CONSTRAINT
    fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post

一对一

一对一的表关系如下:

One-to-one

在关系数据库系统中,一对一的表关系基于子级中的Primary Key列链接两个表,该子表也是Foreign Key引用子项的Primary Key父表行。

因此,我们可以说子表与父表共享Primary Key

在上面的表图中,id表中的post_details列也与Foreign Keypost {{1} }列:

id

多对多

多对多表关系如下所示:

Many-to-many

在关系数据库系统中,多对多表关系通过一个子表链接两个父表,该子表包含引用两个父表的Primary Key列的两个ALTER TABLE post_details ADD CONSTRAINT fk_post_details_id FOREIGN KEY (id) REFERENCES post 列。

在上面的表图中,Foreign Key表中的Primary Key列也与post_id表ID post_tag列具有Foreign Key关系:< / p>

post

并且,Primary Key表中的ALTER TABLE post_tag ADD CONSTRAINT fk_post_tag_post_id FOREIGN KEY (post_id) REFERENCES post 列与tag_id表ID post_tag列具有Foreign Key关系:

tag

答案 3 :(得分:2)

一对一(1-1)关系: 这是初级和初级之间的关系。外键(与外键有关的主键只有一个记录)。这是一对一的关系。

一对多(1-M)关系: 这也是初级和初级之间的关系。外键关系,但这里有与多个记录相关的主键(即表A有书信息,表B有一本书的多个出版商)。

多对多(M-M):多对多包含两个维度,完整地说明如下。

-- This table will hold our phone calls.
CREATE TABLE dbo.PhoneCalls
(
   ID INT IDENTITY(1, 1) NOT NULL,
   CallTime DATETIME NOT NULL DEFAULT GETDATE(),
   CallerPhoneNumber CHAR(10) NOT NULL
)
-- This table will hold our "tickets" (or cases).
CREATE TABLE dbo.Tickets
(
   ID INT IDENTITY(1, 1) NOT NULL,
   CreatedTime DATETIME NOT NULL DEFAULT GETDATE(),
   Subject VARCHAR(250) NOT NULL,
   Notes VARCHAR(8000) NOT NULL,
   Completed BIT NOT NULL DEFAULT 0
)
-- This table will link a phone call with a ticket.
CREATE TABLE dbo.PhoneCalls_Tickets
(
   PhoneCallID INT NOT NULL,
   TicketID INT NOT NULL
)