是否可以仅使用2个表实现任意关系?

时间:2010-12-18 01:43:00

标签: sql sql-server sql-server-2008

我不知道下面我的想法是否适用:

我有两张桌子,分别是A和B.

表A中的每一行都可以与表B的零行或多行相关联。 表B中的每一行也可以与表A的零行或多行相关联。

表A包含(其中)2列AId(作为主键)和BId(作为外键)。 表B还包含(其中包括)2列BId(作为主键)和AId(作为外键)。

还为DB和模型类中的每个外键关系设置了级联删除规则。 这意味着删除一行A也会删除与之关联的B 的行,删除一行B将删除与之关联的A行。

这种情况几乎可以实现吗?

4 个答案:

答案 0 :(得分:7)

不,如果您遵循正常形式则不行。

多对多关系是需要交叉表的标志。

更多信息:

所以这是一个例子。问题标记。标签可以包含多个问题,而问题可以包含多个标签。这是一个多对多的现实。您可以在Question实体的Tag列中放入多个tagIds条目。但是你这样做会失去很多。

您将无法保持诚信,因为无论标记表和问号标记列中是否存在标记都非常难以维护。

这也违反了正常形式,因为单个列不能有多个值。

您也无法轻松加入该列,因为它中包含多个值。

答案 1 :(得分:2)

您需要的是一个联接表。因此,您有一个ab表,每个表都有一个主键。然后创建一个只有2列的ab表。两者都是外键。一个进入a表,另一个进入b表。

Google for"数据库规范化"。你会发现很多例子。

答案 2 :(得分:2)

这是可能的,但你绝对不希望这样做。

您可以在其中一个表中使用逗号分隔的标识字符串。从那张桌子到另一张桌子查找价值当然是一个很大的麻烦。从另一张表中查找值是一场噩梦。

使用此方法的级联触发器当然是不可能的。通过使更新触发器完成工作可能是可能的,但是它的性能会非常糟糕,以至于没有意义。

为了有效地做到这一点,你绝对需要另一张关系表。

答案 3 :(得分:2)

我假设您所指的“任意 - 任何”关系'many-to-many'

您在帖子中描述的内容并非多对多关系。你所描述的是两个独立的一对多关系。

通过TableB中的AId列,您具有从TableA到TableB的一对多关系。并且您通过TableA中的BId列从TableB到TableA有另一个一对多关系。在相反方向上具有两个一对多关系与拥有多对多关系不是一回事。以Stefan的标记示例为例,考虑三个查询(QId1,QId2和QId3)和三个标记(TId1,TId2和TId3)。尝试表示所有QId1,QId2和QId3都标记有所有TId1,TId2和TId3。你会意识到你不能,因为你试图只在6个可用的“外键”字段中表达9种关系。一个真正的多对多关系需要在两个大小为M和N的表之间达到MxN'链接',而你的设计允许M + N(这并不奇怪,因为你的设计是1到1之一的M链接 - 多个关系和另一个1对多关系中的另外N个链接。)