Database 什么';在SQL中处理一对一关系的最佳方法是什么?

Database 什么';在SQL中处理一对一关系的最佳方法是什么?,database,linq,linq-to-sql,database-design,schema,Database,Linq,Linq To Sql,Database Design,Schema,假设我有阿尔法的东西,可能与布拉沃或查理的东西有关,也可能与之无关 这是一对一的关系:没有阿尔法将涉及到一个以上的布拉沃。没有比一个阿尔法更重要的了 我有几个目标: 易于学习和使用的系统 维持 在我的 数据库 与 现实世界中的逻辑组织 我的数据 我的系统中的类/对象 很好地映射到 数据库表(从Linq到SQL) 快速读写操作 有效利用空间(很少有空字段) 我有三个想法 PK = primary key FK = foreign key NU = nullable 一个包含许多空字段

假设我有阿尔法的东西,可能与布拉沃或查理的东西有关,也可能与之无关

这是一对一的关系:没有阿尔法将涉及到一个以上的布拉沃。没有比一个阿尔法更重要的了

我有几个目标:

  • 易于学习和使用的系统 维持
  • 在我的 数据库
  • 与 现实世界中的逻辑组织 我的数据
  • 我的系统中的类/对象 很好地映射到 数据库表(从Linq到SQL)
  • 快速读写操作
  • 有效利用空间(很少有空字段)
我有三个想法

PK = primary key  
FK = foreign key  
NU = nullable
一个包含许多空字段的表(平面文件)

许多具有零nullalbe字段的表

      Alphas
      --------
   PK AlphaId
      AlphaOne
      AlphaTwo
      AlphaThree

      Bravos
      --------
FK PK AlphaId
      BravoOne
      BravoTwo
      BravoThree

      Charlies
      --------
FK PK AlphaId
      CharlieOne
      CharlieTwo
      CharlieThree
两者中最好的(或最差的):许多表都有许多空外键

      Alphas
      --------
   PK AlphaId
      AlphaOne
      AlphaTwo
      AlphaThree
NU FK BravoId
NU FK CharlieId

      Bravos
      --------
   PK BravoId
      BravoOne
      BravoTwo
      BravoThree

      Charlies
      --------
   PK CharlieId
      CharlieOne
      CharlieTwo
      CharlieThree
如果阿尔法必须是布拉沃或查理,但不是两者都是呢

如果阿尔法也可以是三角洲、回声、狐步、高尔夫等等,而不仅仅是布拉沃和查理,那会怎么样



编辑:这是问题的一部分:

另外一种方法是使用3个表来存储3个实体,并使用一个单独的表来存储关系。

就我个人而言,我在您的第二个模型上取得了很大成功,在一列上使用PK/FK

我从来没有遇到过这样的情况:所有的阿尔法人都必须在布拉沃或查理表格中记录。我一直在处理10..1,从来没有处理过11


至于你的最后一个问题,那只是更多的表。

你可以有一个连接表来指定Alpha和相关ID。然后你可以添加另一列,指定它是否是Bravo、Charlie或其他的ID。保持列在Alpha上向下移动,但确实增加了连接查询的复杂性。

除非我有充分理由不这样做,否则我会选择选项1。它可能不会花费你想象的那么多空间,特别是如果你在布拉沃使用varchars。不要忘记,拆分它将花费外键、辅助标识和所需的索引。
如果不太可能需要Bravo,您可能会遇到麻烦(如果您希望每个Alpha只与一个Bravo相关,我会投票支持使用组合FK/PK的可能性:

      Bravos
      --------
FK PK AlphaId
      BravoOne
      BravoTwo
      BravoThree
这样一来,只有一个Bravo可以引用你的Alpha

如果Bravos和Charlies必须相互排斥,最简单的方法可能是创建一个鉴别器字段:

      Alpha
      --------
   PK AlphaId
   PK AlphaType NOT NULL IN ("Bravo", "Charlie")
      AlphaOne
      AlphaTwo
      AlphaThree

      Bravos
      --------
FK PK AlphaId
FK PK AlphaType == "Bravo"
      BravoOne
      BravoTwo
      BravoThree

      Charlies
      --------
FK PK AlphaId
FK PK AlphaType == "Charlie"
      CharlieOne
      CharlieTwo
      CharlieThree

通过这种方式,AlphaType字段强制记录始终只属于一个子类型。

到目前为止,我有一个非常适合您的模型的示例:

我有Charlie和Bravo表,它们的外键alpha_id来自alpha。与第一个示例一样,除了alpha不是主键之外,Bravo_id和Charlie_id是主键

我在每个需要寻址到这些实体的表上都使用了alpha_id,因此,为了避免SQL可能会导致延迟研究Bravo和Charlie以找到哪一个alpha,我创建了一个AlphaType表,在alpha表上我有它的id(alpha_type_id)作为外键。这样我就可以通过编程的方式知道我在处理哪个字母类型,而不必连接可能有无数记录的表。在tSQL中:

// For example sake lets think Id as a CHAR.
// and pardon me on any mistake, I dont have the exact code here,
// but you can get the idea

SELECT 
  (CASE alpha_type_id
    WHEN 'B' THEN '[Bravo].[Name]'
    WHEN 'C' THEN '[Charlie].[Name]'
    ELSE Null
  END)
FROM ...

我将创建一个超类型/子类型关系

   THINGS
   ------
PK ThingId  

   ALPHAS
   ------
FK ThingId (not null, identifying, exported from THINGS)
   AlphaCol1
   AlphaCol2
   AlphaCol3  

   BRAVOS
   ------
FK ThingId (not null, identifying, exported from THINGS)
   BravoCol1
   BravoCol2
   BravoCol3  

   CHARLIES
   --------
FK ThingId (not null, identifying, exported from THINGS)
   CharlieCol1
   CharlieCol2
   CharlieCol3
例如,一个阿尔法有一个查理,但没有一个布拉沃:-

insert into things values (1);
insert into alphas values (1,'alpha col 1',5,'blue');
insert into charlies values (1,'charlie col 1',17,'Y');

请注意,您不能为alpha创建多个charlie,就好像您试图创建一个ThingId为1的两个charlies一样,第二次插入将得到唯一的索引/约束冲突。

您提出了许多问题,如果不对您正在尝试的确切问题进行更多澄清,就很难选择任何建议的解决方案不要仅仅考虑我的澄清问题,而是考虑你用来评价我的问题的标准,来说明解决问题所需的细节量:

  • 易于学习和维护的系统
什么“系统”易于学习和维护?应用程序的源代码,或通过其最终用户界面获取的应用程序数据

  • 在我的数据库中强制执行数据完整性
您所说的“在我的数据库中强制”是什么意思?这是否意味着您不能以任何其他方式控制数据完整性,即项目只需要基于数据库的数据完整性规则

  • 与数据的真实逻辑组织相匹配的架构
你能给我们提供你所指的真实世界和逻辑组织吗?从你试图存储的三个数据示例中无法推断出来——也就是说,假设你的三个结构都是完全错误的。除非我们知道真实世界的规范,否则我们怎么知道

  • 编程中映射到数据库表的类/对象(从Linq到SQL)
这个要求听起来像是你的手被迫用LINQtoSQL创建的,是这样吗

  • 快速读写操作
什么是“快速”?.03秒?3秒?30分钟?不清楚,因为您没有指定所指的数据大小和操作类型

  • 有效利用空间(很少有空字段)

空间的有效使用与空字段的数量无关。如果您指的是规范化的数据库结构,那么这将再次取决于实际的规范和应用程序中未提供的其他设计元素。

我假设您将使用SQL Server 2000/2005。我有一个标准模式对于我使用的1对1关系,这与你的第二个想法没有太大的不同,但这里有一些区别:

  • 每个实体首先都必须有自己的主键,所以Bravo、Charlie等表应该在ad中定义自己的代理键
    insert into things values (1);
    insert into alphas values (1,'alpha col 1',5,'blue');
    insert into charlies values (1,'charlie col 1',17,'Y');