【问题标题】:Using Normalisation would cause a mysql query error [closed]使用规范化会导致 mysql 查询错误 [关闭]
【发布时间】:2023-03-06 05:51:01
【问题描述】:

我正在尝试建立一个小型社区网站,人们可以在其中加入和发布新闻文章、博客、个人故事等,当规范化问题出现时,我已经创建了该网站和大多数数据库表。现在我对这个主题知之甚少,但在过去的几天里一直在研究它,即使我理解得更好了,我仍然可以看到它在某些情况下可能不相关,比如我的。

以下是场景 - 我的网站允许人们加入并发布他们自己的文章,并且他们可以通过为每篇文章或他们的博客提供一个个人类别来个性化他们的页面。因此,例如,我可以将一个类别称为“英国生活”,而其他人可能会说“利兹生活”,这完全取决于他们。

这是我的 MySQL 表:

+------+--------------------+------------------------+--------------------------+
| ID   | Category           | Title                  | Article                  |
+------+--------------------+------------------------+--------------------------+
| 01   | life-in-leeds      | Title For This Article | Text for this article... |
| 02   | life-in-leeds      | Title For This Article | Text for this article... |
| 03   | business           | Title For This Article | Text for this article... |
| 04   | professional-stuff | Title For This Article | Text for this article... |
+------+--------------------+------------------------+--------------------------+

所以有些人建议我有一个类别表,因为上表中的数据是重复的。所以现在的表格是:

+----+--------------------+
| ID | Category           |
+----+--------------------+
| 01 | life-in-leeds      |
| 02 | business           |
| 03 | professional-stuff |
+----+--------------------+

+------+----------+------------------------+--------------------------+
| ID   | Category | Title                  | Article                  |
+------+----------+------------------------+--------------------------+
| 01   | 01       | Title For This Article | Text for this article... |
| 02   | 01       | Title For This Article | Text for this article... |
| 03   | 02       | Title For This Article | Text for this article... |
| 04   | 03       | Title For This Article | Text for this article... |
+------+----------+------------------------+--------------------------+

假设 user_1 拥有类别 01 和类别 02,总共有 10 篇文章,其中 5 篇是类别 01,另外 5 篇是类别 02。假设他删除了这两个类别,所以现在它们都设置为未分类查询时会出现问题,因为即使它们都未分类,但它们都有不同的 ID,因此在搜索任一类别时,只会显示 5 个。那么保留它在原始表中的方式然后用php更改它不是更好吗,例如将 $life-in-leeds 替换为 $new-category where owner == $owner_name?

【问题讨论】:

  • 我不太明白。当他删除类别时,他们的id不应该设置为NULL(在文章表中)吗?然后您将有 10 条没有类别的记录,并且无法通过它们以前的类别进行区分
  • 这就是我要说的@kingkero - 如果需要在articles 表中更改记录,为什么还要单独的categories 表?
  • 正确设置外键后,您无需更改。当类别中的某些内容发生变化时,拥有ON UPDATE CASCADE ON DELETE SET NULL 之类的东西会自动更改文章表。假设用户删除了一个分类,你只需要删除指定的行,文章表中对应的category_ids就会被设置为NULL
  • 如果你有这样的行为,为什么不添加一个实体来存储有关用户类别的数据?顺便说一句,规范化真的很简单,只有三个规则:1)你必须有一个主键; 2)你必须有外键; 3) 不得将汇总结果存储在表格中。
  • @kingkero 哦,我明白了,所以这都是关于分配外键的。我在博客中看到过它,但没有进一步研究

标签: php mysql sql database-design normalization


【解决方案1】:

规范化并不意味着“用 id 数字替换文本”。

我们有第一范式 (1NF)、Boyce-Codd 范式 (BCNF) 和第六范式 (6NF)。我们没有像“我用 id numbers 替换文本”这样的正常形式。这不是意外。

看看this example from Wikipedia。它从这个表开始,它在 2NF 中。候选键是 {Tournament, Year}。

比赛获胜者 比赛年份 获胜者 获胜者 出生日期 -- 1998 年印第安纳邀请赛 Al Fredrickson 1975 年 7 月 21 日 1999 年克利夫兰公开赛鲍勃·艾伯森 1968 年 9 月 28 日 1999 年得梅因大师赛 Al Fredrickson 1975 年 7 月 21 日 1999 年印第安纳邀请赛 Chip Masterson 1977 年 3 月 14 日

文章展示了这种分解,旨在去除传递依赖Winner->Winner Date of Birth

比赛获胜者 锦标赛年冠军 -- 1998年印第安纳邀请赛阿尔弗雷德里克森 克利夫兰公开赛 1999 鲍勃·艾伯森 得梅因大师赛 1999 阿尔弗雷德里克森 印第安纳邀请赛 1999 Chip Masterson 获胜者出生日期 获胜者出生日期 -- 芯片马斯特森 1977 年 3 月 14 日 阿尔弗雷德里克森 1975 年 7 月 21 日 鲍勃·艾伯森 1968 年 9 月 28 日

这两个表现在至少在 5NF 中,对吧?这是重要的部分。

  • 原始表有四列。
  • 决赛桌都没有四列。

为什么这很重要?删除依赖项总是会减少您开始使用的表中的列数。

如果您所做的任何事情都不会减少您开始使用的表中的列数,那么这不是规范化。它可能有用。这可能是明智的。但这不是规范化。

您的表格以四列开始,以四列结束。它以一列标识一篇文章的类别开始,并以一列标识一篇文章的类别结束。您开始的表格和结束的表格的正常形式是相同的。就规范化而言,您的更改没有任何作用。

话虽如此,规范化并不是您在设计数据库时唯一需要考虑的事情。您可以通过添加这样的表来提高数据完整性。

类别 类别 -- 生活在利兹 商业 专业的东西

然后设置一个从articles.category 到category.category 的外键。现在您的数据库可以拒绝拼写错误的类别。另一方面,您现在必须有一个特殊的过程来将新类别添加到数据库中。

【讨论】:

    猜你喜欢
    • 2019-06-14
    • 2020-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-09
    • 2019-04-21
    相关资源
    最近更新 更多