5

如何为可以与自身具有一对多关系的实体构建表?具体来说,我正在开发一个跟踪动物繁殖的应用程序。每只动物都有一个ID;它还有一个父亲身份证和一个女士身份证。因此,从父系或母系到其后代,有可能是一对多的。我会倾向于这样的事情:

ID INT NOT NULL PRIMARY KEY
SIRE_ID INT 
DAME_ID INT

并将购买并添加到种畜的那些动物记录为空值,并在表格中记录其余的ID。

所以:

  1. 有人可以指出我讨论建模这种关系的文章/网页吗?
  2. ID 应该是 INT 还是某种字符串?INT 中的 NULL 表示该动物在数据库中没有父母,但可以使用具有特殊标志值的字符串来表示相同的事情。
  3. 这可能最好通过两个表建模吗?我的意思是一张动物表和一张单独的表,仅表明亲属关系,例如:

    动物

    ID INT NOT NULL 主键

    亲属关系

    ID INT NOT NULL PRIMARY KEY FOREIGN KEY

    SIRE_ID INT 主键 外键

    DAME_ID INT 主键 外键

我为上述道歉:我的 SQL 生锈了。我希望它能表达我的想法。

4

9 回答 9

6

好吧,这是一种“正常”的一对多关系,您建议的方法是解决它的经典方法。

请注意,两个表是非规范化的(我无法准确指出 superkey-is-not-well-should-be-subset-of-other-key-fsck-I-forgot 部分在哪里,但我很确定它在某处);直观的原因是第一个中的一个元组最多匹配第二个中的一个元组,所以除非你有很多动物的父亲和贵妇人 ID 为空,否则这在任何前景中都不是一个好的解决方案(它会降低性能 - 需要加入——并且不会减少存储需求)。

于 2008-10-01T22:04:42.937 回答
4

我认为您只使用一张桌子的布局很好。您肯定希望将 SIRE_ID 和 DAME_ID 保持在与 ID 相同的数据类型中。您还希望将它们声明为 FOREIGN KEY(可能有一个外键指向同一个表,并且外键也可以为空)。

ID INT NOT NULL PRIMARY KEY
SIRE_ID INT REFERENCES TABLENAME (ID)
DAME_ID INT REFERENCES TABLENAME (ID)

使用此布局,您可以轻松查找父动物,还可以为给定动物构建后代树(对于 Oracle,有 CONNECT BY)

于 2008-10-01T22:11:03.170 回答
3

几个月前,我在 MySQL 网站上问了一个类似的问题。我建议你看看我从 Peter Brawley 那里收到的关于这种关系的回复:http://forums.mysql.com/read.php?135,187196,187196#msg-187196

如果您想进一步研究该主题,那么我建议您查看 Wikipedia 上的 Tree Hierarchies。

另一个建议的架构(将完全标准化)如下所示:

表:动物

身份证 | 姓名 | 品种

表:血统

动物ID | parent_id | parentType(父亲或母亲)

于 2008-10-01T22:06:00.157 回答
1

INT 是 ID 列的更好选择,如果您应该使用序列来生成唯一 ID,则更适合。

我认为将设计拆分为两个表没有任何好处。

于 2008-10-01T22:05:43.747 回答
1

我不知道动物繁殖,但听起来您的 Sire_ID 是父亲,而 Dame_ID 是母亲?没问题。每只动物一行,购买的动物为 null sei_和 dame_ID,我不认为有任何问题。

[ID],[Sire_ID],[Dame_ID];
0,null,null  (male)
1,null,null  (female)
2,null,null  (female)
3,0,1 (male)
4,0,2 (male)
5,null,null  (female)
6,3,5
7,4,5

等等。您可能会在 while 循环中填充 TreeView 或 XmlNodeList ......

While (myAnimal.HasChildren) {
 Animal[] children = GetChildren(Animal.ID)
 for (int x=0; x<children.length; x++) 
  myAnimal.Children.Add(children[x]);
}

在这种情况下,Animal.Children 是动物的集合。因此,myAnimal.Children[0].Father 将返回 myAnimal。.Parent[] 可以是它的两个父母的集合,只要 [0] 始终是一个父母(父亲)并且 [1] 始终是另一个父母(母亲),它就应该起作用。

使 ID 成为自动编号 PK,并通过返回其父项的 ID 以编程方式分配 Sire_ID 和 Dame_ID。尽管如果您真的想要两个父 ID 都可以引用回 ID,但应该不需要外键关系。

于 2008-10-01T22:14:27.813 回答
0

使用带有 SQL 的“connect by”子句来告诉它要遵循哪个层次结构。

于 2008-10-01T22:06:46.537 回答
0

这不是真正的一对多关系,除非动物可以有很多父母。

我会将它保留为一个单独的表,其中包含动物的唯一键 ID、每个父母的一个 int 字段,可能还有一个文本字段用于关于动物的一般注释,如果是这种情况,它是在哪里购买的。

于 2008-10-01T22:07:22.057 回答
0

我认为既然很明显一只动物只有一个父亲和一个大坝,那么使用一张桌子是最有意义的。我的偏好是使用 int 或 bigint 作为行标识符,空值表示没有关系。那么,我可能会使用其他一些方法来唯一地识别动物,这样它们就不会在表中出现两次,并且也会在该列上创建一个唯一索引。

于 2008-10-01T22:10:51.143 回答
0

好像你想建造像树一样的东西。

类似的东西呢?:

 ID          Primary Key,
 Parent_ID   Foreing_Key
 ( data )

有一些功能可以在与自身有关系的表中进行查询。请参阅Connect By的语法:http : //www.adp-gmbh.ch/ora/sql/connect_by.html

于 2008-10-01T22:13:22.510 回答