一个连接表(联结表)可以用于一对多的关系吗?

14

根据定义,一个连接表(桥接表/链接表)用于多对多的关系,在如下情况中使用:

CREATE TABLE Users
(
UserLogin varchar(50) PRIMARY KEY,
UserPassword varchar(50) NOT NULL,
UserName varchar(50) NOT NULL
)


CREATE TABLE Permissions
(
PermissionKey varchar(50) PRIMARY KEY,
PermissionDescription varchar(500) NOT NULL
)


--This is the junction table.
CREATE TABLE UserPermissions
(
UserLogin varchar(50) REFERENCES Users (UserLogin),
PermissionKey varchar(50) REFERENCES Permissions (PermissionKey),
PRIMARY KEY (UserLogin, PermissionKey)
)

但是它也可以被用于一对多的关系,例如在这个例子中,一个用户与多个订单相关联:

(我不太懂数据库,如果我有什么误解,请纠正我。)

CREATE TABLE Users
(
UserLogin varchar(50) PRIMARY KEY,
UserPassword varchar(50) NOT NULL,
UserName varchar(50) NOT NULL
)


CREATE TABLE Orders
(
OrderKey varchar(50) PRIMARY KEY,
OrderDescription varchar(500) NOT NULL
)


--This is the junction table.
CREATE TABLE UserOrders
(
UserLogin varchar(50) REFERENCES Users (UserLogin),
OrderKey varchar(50) REFERENCES Orders (OrderKey),
PRIMARY KEY (UserLogin, OrderKey)
)
6个回答

12
是的,在联结表中仍然可以存储和强制实施一对多关系。
在您的示例中,您没有对“UserOrders”联结表施加任何约束条件,因此单个订单可能属于两个用户(假设这是不正确的)。要强制执行,您可以使“OrderKey”成为“UserOrders”联结表的主键(或在该列上具有唯一约束)。从技术上讲,这将成为“UserOrders”和“Users”之间的多对一关系,同时在“Orders”和“UserOrders”之间具有一对一关系。
我只能想到一个设计使用联结表进行多对一关系的原因 - 如果您计划允许未来的多对多关系并且不想处理数据迁移。但与此同时,您将支付存储和连接附加表的成本。

1
有时候,如果您想要具有相同的数据库表结构,但在应用程序中决定关系类型:一对多或多对多(作为参数),这可能会很方便。 有时候,您开发一对多关系时知道很可能会变成多对多。 - m_vitaly
我明白了。如果你想在数据库中实现一对多或多对多的关系,你可以使用某种类型的约束来实现吗? - pez_dispenser
@jt 如果你在谈论联合表,那么你不能仅使用该表来强制执行一对多关系。否则,你的意思是通过“外键”约束来强制执行它。在一对多关系中,“多”方有一个带有约束的字段,这意味着每行必须指向“一”方(在外键列中具有一方的ID,并且不允许其他值存在)。 - m_vitaly
4
在联接表中,你可以通过在1或2列上分别施加唯一约束来轻松强制实现一对多或一对一的关系。 - Bart van Heukelom
@philipxy 这正是答案所说的,你将约束检查留给应用程序而不是在数据库中强制执行它。在某些情况下可能很有用,例如您想要在将来更改应用程序代码以添加对多对多的支持而无需更改和迁移数据库中的数据。 - m_vitaly
显示剩余2条评论

10

没有理由不能使用连接表来处理一对多关系。问题通常在于性能。如果不必要,为什么让数据库加入额外的表进行连接呢?


8
如果外键大多数情况下都是NULL,那么怎么办?如果联接表或这些表之间的关联很少被查询或联接,那么使用节省空间的联接表是否更好? - Clint Pachl

5
这将是多对多关系:
CREATE TABLE UserOrders
(UserLogin varchar(50) REFERENCES Users (UserLogin),
OrderKey varchar(50) REFERENCES Orders (OrderKey),
PRIMARY KEY (UserLogin, OrderKey));

这将是一对多的关系(一个用户有多个订单):
CREATE TABLE UserOrders
(UserLogin varchar(50) REFERENCES Users (UserLogin),
OrderKey varchar(50) REFERENCES Orders (OrderKey),
PRIMARY KEY (OrderKey));

请注意主键约束的区别。

3
一旦您创建了一个表,它实际上没有“交叉点”表、 “联合”表或“连接”表的类型——它只是一个表。我们使用这些术语来描述一个实体(和相应的表)最初被创建的特定原因。联接实体最初是为了解决多对多的情况而创建的。但是这些表往往具有自己的属性(例如关联时间、关联原因等)。因此,SQL Server、Oracle或您的代码无需知道表是为什么创建的,只需要知道它是一个表。从技术角度来看,关联表与任何其他表之间实际上没有任何区别。因此,这些表可以扮演任何其他表所能扮演的角色。没有规定其他表如何与它们相关联。

0

我认为你对概念的理解有误 - 如果可以的话,这里是简单的解释: 要在两个表(比如A和B)之间实现多对多关系,我们需要借助一个连接表(比如表C),该表将与表A和表B都建立一对多关系。


0
你可以在连接/联接表中强制执行“一”的约束,通过向作为“多”方的外键列添加唯一约束(或将其设置为连接表的主键,因为该属性本身就能够标识关系),这样做可以确保“多”方的行只有一个关系,并且关系都在连接/联接表中声明。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接