如何引用关系数据库中的记录组?

问题描述 投票:3回答:2

假设我们有以下表结构:

人类

| HumanID | FirstName | LastName | Gender |
|---------+-----------+----------+--------|
|       1 | Issac     | Newton   | M      |
|       2 | Marie     | Curie    | F      |
|       3 | Tim       | Duncan   | M      |

动物

| AmimalID | Species | NickName |
|----------+---------+----------|
|        4 | Tiger   | Ronnie   |
|        5 | Dog     | Snoopy   |
|        6 | Dog     | Bear     |
|        7 | Cat     | Sleepy   |

我想知道如何在其他表中引用一组记录。

例如,我有一个Foods表和一个EatenBy列。

食品

| FoodID | FoodName | EatenBy |
|--------+----------+---------|
|      8 | Rice     | ???     |

我想在EatenBy中存储的内容可能是

  1. 人类中的单一记录,动物表(例如Tim Duncan)
  2. 表中的一组记录(例如所有狗,所有男性,所有女性)
  3. 整张桌子(例如所有人类)

一个简单的解决方案是使用连接字符串,其中包括来自不同表的主键和特殊字符串,如“Humans”,“M”。应用程序可以解析连接的字符串并相应地执行操作。

食品

| FoodID | FoodName | EatenBy      |
|--------+----------+--------------|
|      8 | Rice     | Humans, 6, 7 |

我知道从关系数据库设计的角度来看,使用串联字符串是一个坏主意。

另一种选择是添加另一个表并使用外键。

食品

| FoodID | FoodName |
|--------+----------|
|      8 | Rice     |

EatenBy

| FoodID | EatenBy |
|--------+---------|
|      8 |  Humans |
|      8 |       6 |
|      8 |       7 |

我认为它比第一个解决方案更好。问题是EatenBy字段存储了不同含义的值。那是问题吗?

模拟此要求的最佳方法是什么?在这种情况下如何实现3NF?

这里的示例表有点人为,但我确实在工作中碰到这样的情况。我看过很多表只使用连接字符串。我认为它很糟糕但却无法想出一种更为关联的方式来处理它。


Quick Answer

对于那些想快速了解这个问题的答案的人。这是基本的想法:

  1. 不应在关系模型中使用连接字符串,CSV,重复组。所以我们需要对表进行规范化,从而消除重复的组。
  2. 在这个问题中,连接的字符串包含不同含义的值。 关系数据库存储有关现实世界的事实。每个表应存储关于一个主题的事实,每个列应存储一个事实。 因此,我们需要一个关联表来为每个事实修复“EatenBy”。 例如 Food_Human(FoodID,HumanID) Food_Animal(FoodID,AnimalID) Food_Species(FoodID,SpeciesID)

警告

解决问题的想法很好。但是,这里的数据模型很糟糕。

明显的问题:

  1. 人类是动物
  2. 在数据建模期间使用代理(ID)是不好的做法
relational-database database-normalization referential-integrity
2个回答
4
投票
  1. 本答复按时间顺序排列。该问题在细节方面取得了进展,称为更新。有一系列匹配的响应。
  2. 从初始问题到最终答案的进展是一种学习体验,特别是对于OO / ORM类型。主要标题标记回复,次要标题标记主题。
  3. 答案超过了超出的最大长度。我提供它们作为链接,以克服这一点。

Response to Initial Question

就目前而言,你的问题无法回答。因此......这不是答案,这是方向,以便您在问题中添加相关详细信息,以便我们提供答案。请不要对此投票。

你可能在工作中看到过类似的东西,但这并不意味着它是正确的,或者是可接受的。 CSV打破2NF。您无法轻松搜索该字段。您无法轻松更新该字段。您必须通过代码手动管理内容(例如,避免重复;排序)。你没有数据库或任何类似的数据库,你有一个宏大的记录文件系统,你必须编写大量的代码来“处理”。就像1970年ISAM数据处理过去的糟糕时期一样。

  1. 问题是,你似乎想要一个关系数据库。也许您已经听说过数据完整性,关系功率(在此阶段为您加入功率)和速度。记录文件系统没有这个。 如果您想要一个Relational数据库,那么您将不得不: 相关地思考数据,并将关系数据库方法(例如数据建模)应用为数据,而不是数据(而不是数据值)。 然后对数据进行分类(与OO类或分类器概念无关)。 然后关联分类数据。
  2. 第二个问题是,这是典型的OO类型,他们专注于,着迷于数据值,而不是数据的含义;它是如何分类的;它与其他数据的关系;等等 毫无疑问,你不认为这个概念是你自己,你的“老师”把它喂给你,我一直都在看。他们喜欢唱片系统。请注意,您不是提供表定义,而是声明您提供“结构”,而是列出数据值。 如果您不理解我所说的话,请允许我向您保证,这是OO世界中的经典问题,如果您应用这些原则,解决方案很容易。否则,它在OO堆栈中无穷无尽。最近我完全取消了一个OO提议+解决方案,一位非常着名的支持OO巨石的数学家提出了这个建议。这是一篇着名的论文。 我将数据关联起来(即,我只是将数据放在关系上下文中:建模和规范化它,总共花了十分钟),问题消失了,提案+解决方案不是必需的。阅读Hidders Response。请注意,我并没有试图破坏论文,我试图理解以精神分裂形式呈现的数据,最简单的方法是建立一个关系数据模型。这个简单的行为破坏了报纸。 请注意,该链接是客户(一家大型澳大利亚银行)的付费转让正式报告的摘录,该客户慷慨地允许我发布摘录,以便向公众宣传忽略关系数据库原则的危险,特别是OO的支持者。 完全相同的过程发生在第二个更着名的纸张Kohler Response。这种反应要小得多,不那么正式,对客户来说不是有偿工作。那个特殊的白痴对另一个异常的“正常形式”进行了理论研究。

因此,我会请你:

  • 忘记“表结构”或定义
  • 忘掉你想要的东西
  • 忘记实施选择
  • 忘了ID列,完全和完全
  • 忘了EatenBy
  • 想想你在数据,数据的意义,而不是数据值或示例数据方面所拥有的东西,而不是你想用它做什么
  • 考虑如何对数据进行分类,以及如何对其进行分类。
  • 数据如何与其他数据相关。 (你可能认为你的EatenBy就是这样,但它不是,因为数据还没有组织,形成关系。)

如果我看着我的水晶球,大部分都是黑暗的,但是从我能看到的小小的光斑中,它看起来像你想要的:

  • 事情
  • 物联网
  • 事物与事物群体之间的关系

事物是名词,主题。最终我们将在这些主题之间做一些事情,那就是动词或动作声明。这将形成谓词(一阶逻辑)。但现在不是,现在,我们只想要东西。

现在,如果您可以修改您的问题,并告诉我更多关于您的事物及其含义的信息,我可以为您提供完整的数据模型。


Response to Update 1 re Hierarchy

Record IDs are Physical, Non-relational

如果需要关系数据库,则需要关系密钥,而不是记录ID。此外,使用标记在每个文件上的ID启动数据建模练习会削弱练习。

请阅读this Answer

Hierarchies Exist in the Data

如果您想要完整的话语,请提出一个新问题。这是一个快速摘要。

层次结构在世界上自然发生,它们无处不在。这导致层次结构在许多数据库中实现。关系模型建立在层次模型的基础上,并且是层次模型的一个进步。它极好地支持层次结构。不幸的是,着名的作家并不了解RM,他们只教导20世纪70年代以前的唱片归档系统被标记为“关系”。同样,他们不了解层次结构,更不用说RM中支持的层次结构,因此他们会对其进行抑制。

结果是,必须实现的无处不在的层次结构不被如此识别,因此它们以非常不正确且大规模低效的方式实现。

相反,如果正在建模的数据中出现的层次结构正确建模,并使用真正的Relational构造(关系键,规范化等)实现,那么结果是一个易于使用且易于编码的数据库,以及没有数据重复(任何形式)和极快。它的字面意思是最好的关系。

数据中出现三种类型的层次结构。

  1. 按表格顺序形成的层次结构 这个要求,即对关系密钥的需求,发生在每个数据库中,相反,缺乏它会使数据库广告瘫痪产生一个记录归档系统,而没有任何关系数据库的完整性,功能或速度。 层次结构在关系密钥的形式中清晰可见,它在复合中以任何顺序的表格进行:父,子,孙子等。这对于普通的关系数据完整性是必不可少的,Hidders和95%的数据库实现没有。 Hidders Response有一个很好的Hierarchies示例: 一个。在数据中自然存在 湾OO类型是盲目的[正如Hidders显然是] C。他们没有完整性地实现RFS,然后他们试图在对象层中“修复”问题,增加了更多的复杂性。 虽然我以经典的关系形式实现了层次结构,但问题完全消失了,消除了提出的“解决方案”,本文。关系化消除了理论。 这四个表中的两个层次结构是: Domain::Animal::Harvest Domain::Activity::Harvest 请注意,Hidders不知道数据是一个层次结构;他的RFS没有正确的完整性,因为它不是关系型的;将数据放在Relational上下文中提供了他在其外部寻求的完整性;关系模型消除了所有这些“问题”,并使所有这些“解决方案”变得可笑。 这是another example,虽然建模尚未完成。请务必检查谓词,并在第2页查看实际的密钥。层次结构是: Subject::CategorySubject::ExaminationResult Category::CategorySubject::ExaminationResult Person::Registrant::Candidate::ExaminationResult 请注意,最后一个是业务工具状态的进展,因此Key不会复合。
  2. 一个表中的行的层次结构 通常是某种树形结构,其中有数百万种。对于任何给定的节点,它支持单个祖先或父节点,以及无限制的子节点。如果做得恰当,水平的数量或树的高度(即无限祖先和后代世代)没有限制。 祖先和后代在这里使用的术语是简单的技术术语,它们没有OO的含义和限制。 您需要在服务器中进行递归,以遍历树结构,以便您可以编写递归的简单过程和函数。 这是Messages的一个。请阅读问题和答案,并访问链接的Message Data Model。请注意,搜索者没有提到层次结构或树,因为关系数据库中的层次结构的知识被抑制,但是(从注释中)一旦他看到答案和数据模型,他就会认识到它的层次结构,并且它非常适合他。层次结构是: Message::Message[Message]::Message[::Message[Message]] ...
  3. 通过关联表在一个表中的行的层次结构 此层次结构为多个祖先或父项提供祖先/后代结构。它需要两个关系,因此需要一个额外的关联表。这通常称为物料清单结构。无限高度,递归遍历。 物料清单问题是分层DBMS的一个限制,我们在网络DBMS中部分克服了这一问题。当时这是一个亟待解决的问题,也是E F Codd博士明确要求克服的IBM特定问题之一。当然,他实现了这些目标,并且超越了他们。 这是Bill of Materials hierarchy, modelled and implemented correctly。 请原谅前言,这是一篇文章,跳过前两行,看看底行。 Person :: Progeny也给出了。 层次结构是: Part[Assembly]::Part[Component] ... Part[Component]::Part[Assembly] ... Person[Parent]::Person[Child] ... Person[Child]::Person[Parent] ...

Ignorance Of Hierarchy

与数据中通常存在层次结构的事实分开,由于压制而无法识别它们,因此它们不是作为层次结构实现的,当它们被识别时,它们是在最荒谬的时候实现的。愚蠢的方式。

  • 邻接清单 抑制者笑着说“关系模型不支持等级”,否认它是建立在等级模型上的(每一个都提供了明确的证据,证明他们不知道RM中的基本概念,他们声称这是假装约。)所以他们不能使用这个名字。这是他们使用的愚蠢名称。 通常,实现将认识到数据中存在层次结构,但实现将非常差,受物理记录ID等限制,缺少关系完整性等。 对于如何遍历树,他们无能为力,需要递归。
  • 嵌套集 堕胎,直接来自地狱。记录文件系统中的记录文件系统。这不仅会产生大量重复并破坏规范化规则,而且还会修复文件系统中的记录。 移动单个节点需要重写树的整个受影响部分。亲爱的约会,Darwen和Celko类型。 MS HIERARCHYID数据类型做同样的事情。每次节点改变时,都会给你一大堆混凝土,这些混凝土必须经过锤击和重新浇注。

好吧,它不是那么短暂。

Response to Update 2

Response to Update 3

Response to Update 4


0
投票

对于每个吃食物的类别,您应该添加一个表。例如,如果一种食物可能被某些特定性别吃掉,您将拥有:

  Food_Gender(FoodID,GenderID)

对于人类你会有:

 Food_Human(FoodID,HumanID)

对于动物物种:

 Food_AnimalSpc(FoodID,Species)

对于整个表:

Food_Table(FoodID,TableID)

等等其他类别

© www.soinside.com 2019 - 2024. All rights reserved.