在 SQL Server 中定义一对一关系
Posted
技术标签:
【中文标题】在 SQL Server 中定义一对一关系【英文标题】:Defining a one-to-one relationship in SQL Server 【发布时间】:2009-11-12 14:52:15 【问题描述】:我需要定义一对一的关系,但似乎无法在 SQL Server 中找到正确的方法。
你为什么要问一对一的关系?
我将 WCF 用作 DAL (Linq),并且我有一个包含 BLOB 列的表。 BLOB 几乎不会发生变化,每次进行查询时都传输它会浪费带宽。
我查看了this solution,虽然这似乎是一个好主意,但我可以看到 Linq 在尝试实施这种方法时有点小题大做。
有什么想法吗?
【问题讨论】:
【参考方案1】:一对一实际上经常用于超类型/子类型关系。在子表中,主键也作为父表的外键。下面是一个例子:
CREATE TABLE Organization
(
ID int PRIMARY KEY,
Name varchar(200),
Address varchar(200),
Phone varchar(12)
)
GO
CREATE TABLE Customer
(
ID int PRIMARY KEY,
AccountManager varchar(100)
)
GO
ALTER TABLE Customer
ADD FOREIGN KEY (ID) REFERENCES Organization(ID)
ON DELETE CASCADE
ON UPDATE CASCADE
GO
【讨论】:
感谢上帝,这里有人知道 SQL 和关系数据库。你已经证明了这种关系是显式的。需要明确的是,对于那些不确定关系是否为 1::1 的人,请注意 Customer.ID 也是 Organisation.ID,是唯一的,因此只能有一个任何组织行的客户行。 @PerformanceDBA:关系为1:0..1
,因为它缺少确保父表中的每一行在其中一个子类型表中都有匹配行的约束。对于发布的架构,Organization
中的每一行在 Customer 中可以有 0 行或 1 行,因此是 1:0..1
。
@oneday。谢谢,但是您对表面问题的解释(显而易见)与更深层次的问题无关。您评论的依据,而不是评论本身,是不正确的。你和亚当有同样的误解(后来他删除了他的答案)。这个问题不能在 cmets 中处理。如果您真的对理解关系数据库命名法感兴趣,请提出一个新问题,我会完整回答。我不会回答更多的cmets。
@PerformanceDBA:我删除了我的答案,因为讨论已经转移。根据要求,我发布了一个问题,以便您可以正确回答:***.com/questions/5279984/…【参考方案2】:
为什么不让每张表的外键唯一呢?
【讨论】:
因此,如果我在 tableA = 3 中键入并且在 tableB = 4 中键入,它们在它们的表中是唯一的,但没有关系。 但是,如果你 tableA.id = 3 and tableB.tableAId = 3 and tableB.tableAId 是唯一的,并且你对 tableB 到 tableA 做同样的事情,那么你最多保证有一个到一个。【参考方案3】:没有明确的一对一关系。
但是,由于 tbl1.id 和 tbl2.id 是主键,而 tbl2.id 是引用 tbl1.id 的外键,因此您创建了隐式 1:0..1 关系。
【讨论】:
【参考方案4】:将 1:1 的相关项放在同一张表的同一行中。这就是“关系数据库”中的“关系”的来源——相关的东西放在同一行。
如果您想减少通过网络传输的数据大小,请考虑仅投影所需的列:
SELECT c1, c2, c3 FROM t1
或创建一个仅投影相关列的视图并在需要时使用该视图:
CREATE VIEW V1 AS SELECT c1, c2, c3 FROM t1
SELECT * FROM t1
UPDATE v1 SET c1=5 WHERE c2=7
请注意,BLOB 存储在 SQL Server 中的行外,因此通过垂直分区数据不会节省太多磁盘 IO。如果这些是非 BLOB 列,您可能会受益于您所描述的垂直分区,因为您将执行更少的磁盘 IO 来扫描基表。
【讨论】:
【参考方案5】:这个怎么样。将第一个表中的主键链接到第二个表中的主键。
Tab1.ID (PK) Tab2.ID (PK)
我的问题是我有一个两阶段的流程,其中两个都是必填字段。整个过程可以归类为一个情节(放在同一张表中),但有一个初始阶段和最终阶段。
【讨论】:
我相信这是达米尔在第一个答案中所建议的。 你不能有强制性的双向约束。您需要实现事务,并在 SQL 上下文中按顺序处理它们。然后就很容易了。【参考方案6】:在我看来,不使用 LINQ 查询读取 BLOB 的更好解决方案是在包含除 BLOB 之外的所有列的表上创建一个视图。
然后您可以基于视图创建一个 EF 实体。
【讨论】:
不必为您的帖子签名,SO 会自动为您签名。此外,答案通常应显示执行您建议的代码示例。 :|以上是关于在 SQL Server 中定义一对一关系的主要内容,如果未能解决你的问题,请参考以下文章
如何在 SQL Server 或实体框架中创建没有主键的一对多关系?
求助各位大神,sql server两表间一对多的关系,如何数据整合到一行数据中,问题举例在问题补充中。谢谢..
SQL Alchemy - 从一个实体上的多个一对一关系中删除孤儿[关闭]