【问题标题】:Normalizing a database with "chained" entries使用“链式”条目规范化数据库
【发布时间】:2011-04-02 09:07:54
【问题描述】:

我是数据库设计的新手,我还没有找到一种确定的方法来构建我的词汇数据库。除了不相关的字段,我要存储的数据在概念上是这样的:

单词 1

  • 含义 1(其中 1-n 个)
    • 示例 1(其中 0-n 个)
    • 示例 2
    • ...
  • 意义2
  • ...

单词 2

...

现在,单词由三个属性标识:词名、语言和 POS(词性)。我已将其设置为复合键。根据我的阅读,我认为含义和示例应该放在单独的表格中,可能是这样的:

单词表

  • 钥匙
    • 字名
    • 语言
    • 位置
  • ...

含义表

  • 钥匙
    • 字名
    • 语言
    • 位置
  • 含义(每个键 1-n 行)

示例表

  • 钥匙
    • 字名
    • 语言
    • 位置
    • 意义
  • 示例(每个键 0-n 行)

但这让我觉得数据重复的数量惊人。将 wordname-language-POS 键抽象到一个单独的表中并给每一行一个唯一的键会更好吗?有没有更好的方法?

非常感谢。

【问题讨论】:

  • 我现在知道该怎么做。感谢大家的建议。

标签: database-design normalization


【解决方案1】:

一般来说,您可以通过为每个表的每一行生成唯一键来省去一些麻烦,其中键是一个简单的整数,而不是实际数据。外键引用更容易,您不必处理诸如“哎呀,有人拼错了一个单词,但该单词现在是另一个表中外键的一部分!”之类的问题。当键值发生变化时,强制执行外键完整性的数据库确实会让生活变得困难。

而且,正如您所注意到的,使用单词和其他信息作为外键是很多重复的。规范化的全部意义(好吧,无论如何,其中之一)是消除重复。

大多数数据库引擎都会为您生成这些密钥,通常带有一个名为“身份”的属性。当插入新数据时,这些数据库通常有一种简单的方法来以编程方式检索这些密钥。然而,这更多地涉及代码和实现。

【讨论】:

  • IDENTITY 是特定于 SQL Server 的;在 MySQL 中,它们被称为 auto_increment - 每个表都只允许一个。 Oracle & PostgreSQL 使用序列...
  • 谢谢;我忘记了 MySQL 术语。 Oracle 的序列非常痛苦,因为它们必须与触发器配对——除非他们知道自己在做什么,否则我永远不会向他们推荐。
【解决方案2】:

您在正确的轨道上,但请注意存在列限制。

  1. MEANING 表中,key 将是WORD.key 值的外键 - 这允许您与WORD 表中的值相关联,而无需在MEANING 表中重复它们.
  2. 如果你让MEANING.key不是唯一的,你可以支持无限的MEANING.meaning

例子

单词

  • 键(主键)
  • 字名
  • 语言
  • 位置

例子:

key   wordname    language   POS
----------------------------------
1     'foobar'    'English'  idk

含义

  • 意义
  • 两列的唯一约束以停止重复

例子:

key    meaning
----------------
1      'a'
1      'b'

如果你想要意义值的顺序,你必须定义一个列来以某种方式指示顺序 - IE:meaning_id

【讨论】:

    【解决方案3】:

    我也提倡整数键。然后您的表格变得非常简单:

    单词
    密钥表
    字名
    语言
    PartOfSpeach

    含义
    密钥表
    关键字
    说明

    示例
    密钥表
    关键意义 说明

    给定一个词,然后您可以相对容易地获得给定词的所有含义:

    SELECT m.Description
    FROM Word w, Meaning m
    WHERE w.KeyTable = m.KeyWord
    AND w.WordName = 'Example'
    

    给定单词的示例也相当简单:

    SELECT m.Description, e.Description
    FROM Word w, Meaning m, Example e
    WHERE w.KeyTable = m.KeyWord
    AND m.KeyTable = e.KeyMeaning
    AND w.WordName = 'Example'
    

    【讨论】:

      猜你喜欢
      • 2015-10-30
      • 1970-01-01
      • 2014-08-10
      • 1970-01-01
      • 2014-09-21
      • 2011-11-12
      • 2022-01-11
      • 2012-10-08
      相关资源
      最近更新 更多