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

时间:2015-04-24 02:50:08

标签: relational-database database-normalization referential-integrity

假设我们有以下表结构:

人类

| 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 Ducan)
  2. 表格中的一组记录(例如所有狗,所有男性,所有女性)
  3. 整张桌子(例如所有人类)
  4. 一个简单的解决方案是使用连接字符串,其中包含主键 来自不同的表格和特殊字符串,例如“人类”,“' M'。 应用程序可以解析连接的字符串并相应地执行操作。

    食品

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

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

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

    食品

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

    EatenBy

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

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

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

    这里的示例表有点人为,但我遇到了类似的情况 这在工作中。我看过很多表只使用连接字符串。我认为它很糟糕,但却无法想到更多关系方式来处理它。

    快速回答

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

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

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

      明显的问题:

      1. 人类是动物
      2. 在数据建模过程中使用代理(ID)是不好的做法

2 个答案:

答案 0 :(得分:4)

  1. 本答案按时间顺序排列。该问题在细节方面取得了进展,标注为更新。有一系列匹配的响应

  2. 从初始问题到最终答案的进展是一种学习经历,特别是对于OO / ORM类型。主要标题标记回复,小标题标记主题。

  3. 答案超出了超出的最大长度。我将它们作为链接提供,以便克服这一点。

  4. 对初始问题的回应

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

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

    1. 问题是,您似乎想要一个关系数据库。也许您已经听说过数据完整性,关系功率(在此阶段为您加入功率)和速度。记录文件系统没有这个。

      如果你想要一个关系数据库,那么你将不得不:

      • 关联地考虑数据,并将关系数据库方法(例如数据建模)应用为数据,而不是数据(而不是数据值)。

      • 然后对数据进行分类(与OO类或分类器概念无关)。

      • 然后关联分类数据。

    2. 第二个问题是,这是典型的OO类型,他们专注于,着迷于数据,而不是数据的意义;它是如何分类的;它与其他数据的关系;等。

      毫无疑问,你不认为这个概念是你自己,你的教师和#34;喂它给你,我一直都看到它。他们记录归档系统。请注意,您没有给出表定义,而是声明您提供" structure",而是列出数据值。

      • 如果您不理解我所说的话,请允许我向您保证,这是OO世界中的一个典型问题,如果您应用这些原则,解决方案很容易。否则,它在OO堆栈中无穷无尽。最近我完全取消了一个OO提议+解决方案,一位非常着名的支持OO巨石的数学家提出了这个建议。这是一篇着名的论文。

      • 关系数据(即我只是将数据放在关系上下文中:建模和规范化它,总共花了十分钟),问题就消失了,提案+解决方案不是必需的。阅读Hidders Response。注意,我试图销毁论文,我试图理解以精神分裂形式呈现的数据,最简单的方法是建立一个关系数据模型。这个简单的行为破坏了这篇论文。

      • 请注意,该链接是客户(一家大型澳大利亚银行)的付费转让正式报告摘录,该银行已经允许我发布摘录,以便向公众宣传忽视关系数据库原则的危险,尤其是OO支持者。

      • 完全相同的过程发生在第二篇更着名的论文Kohler Response上。这种反应要小得多,不那么正式,对客户来说不是有偿工作。那个特别的白痴对于另一个异常的正常形式进行了理论判断"。

    3. 因此,我会请你:

      • 忘记"表结构"或定义

      • 忘掉你想要的东西

      • 忘记实施选项

      • 完全忘记ID

      • 忘记EatenBy

      • 根据数据,数据的含义,作为数据值或示例数据来考虑拥有的内容,你想用它做什么

      • 考虑如何对数据进行分类,以及如何对其进行分类。

      • 数据如何与其他数据相关联。 (您可能认为您的EatenBy就是那个,但它不是,因为数据还没有组织,以形成关系。)

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

      • 观光

      • 群组

      • 事物和ThingGroups之间的关系

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

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

      对Update 1层次结构的响应

      记录ID是物理的,非关系的

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

      请阅读this Answer

      数据中存在层次结构

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

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

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

      相反,如果正在建模的数据中出现的层次结构正确建模,并使用真正的Relational构造(关系键,规范化等)实现,则结果易于使用且易于使用代码数据库,以及没有数据重复(以任何形式)并且非常快。它在字面意义上是最关系的。

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

      1. 以表格顺序形成的层次结构

        这个要求,关系密钥的需求发生在每个数据库中,相反,缺少它会削弱数据库广告产生一个记录归档系统,没有关系数据库的完整性,功能或速度。

        层次结构在关系密钥的形式中清晰可见,它在复合中以任何顺序的表格进行:父,子,孙子等。这对于普通的关系数据完整性是必不可少的,Hidders和95的那种%的数据库实现没有。

        Hidders Response有一个很好的Hierarchies示例:

        一个。自然存在于数据中

        湾OO类型是盲目的[正如Hidders显然是]

        ℃。他们没有诚信地实施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中部分克服了。当时这是一个亟待解决的问题,也是IBM F Codd博士明确要求克服的一个具体问题。当然,他实现了这些目标,并且超出了他们的目标。

        这是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] ...
          
      4. 无知层次结构

        分离层次结构通常存在于数据中,由于抑制而无法识别层次结构,因此当它们 被识别时,它们不会被实现为层次结构,它们以最荒谬,最火腿的方式实施。

        • 邻接列表

          抑制器笑着说" 关系模型不支持层次结构",否认它是基于层次模型 (每一个都提供了明确的证据,证明他们不知道 RM 中的基本概念,他们声称这些概念是假设的)。所以他们不能使用这个名字。这是他们使用的愚蠢名称。

          通常,实现会认识到数据中存在层次结构,但实现将非常差,受物理记录ID等限制,缺少关系完整性等。

          他们对于如何遍历树是一无所知,需要递归。

        • 嵌套集

          堕胎,直接来自地狱。记录文件系统中的记录文件系统。这不仅会产生大量重复并破坏规范化规则,而且修复具体的归档系统中的记录。

          移动单个节点需要重写树的整个受影响部分。亲爱的约会,Darwen和Celko类型。

          MS HIERARCHYID数据类型执行相同的操作。每次节点更换时,都会给你一大堆混凝土,这些混凝土必须经过锤击和重新浇注。

        好吧,它不是那么短暂。

        对Update 2的响应

        对Update 3的响应

        对Update 4的响应

答案 1 :(得分:0)

对于每个吃食物的类别,您应该添加一张桌子。例如,如果一种食物可能会被某种特定的性别吃掉,那么您就会:

  Food_Gender(FoodID,GenderID)

对于你将拥有的人类:

 Food_Human(FoodID,HumanID)

对于动物物种:

 Food_AnimalSpc(FoodID,Species)

表示整个表:

Food_Table(FoodID,TableID)

等等其他类别