【问题标题】:Additional information on normalization of database有关数据库规范化的附加信息
【发布时间】:2014-03-28 02:46:22
【问题描述】:

我对规范化有点困惑。

有人可以在这个数据库中给出一个真实的例子吗?如果这样可以吗?谢谢。

表:account_info

学生编号(PK)

学生用户名

学生密码

表:student_info

学生编号(PK)

学生姓名

学生课程

学生年

学生节

表:student_subject

学生编号(PK)

student_subject_1

.

.

.

student_subject_10

关于外键,我可以在上面给出的表格中使用它吗?

何时何地是使用它的最佳时间?

【问题讨论】:

  • 你对规范化的哪一部分感到困惑?
  • 也许您应该先尝试搜索引擎:studytonight.com/dbms/database-normalization.phpmycigroup.com/Documents/Academics/DatabaseNormalization.pdfsqa.org.uk/e-learning/SDM04CD/page_01.htm 只是使用 Google 的前三个结果。他们都有很好的例子,可以回答你的问题——不管这是什么问题。
  • @MikeSherrill'CatRecall' .. 我不只是很确定我的数据库设计是否已经正常化,或者它仍然需要改进,很奇怪吧?
  • 您发布的示例未规范化。
  • @DanBracuk 来自 feela 给出的链接,>Table: student_detail >>Student ID |姓名 |邮编>表格:student_address >> ZIP |街道 |城市 |状态与 >table 不一样:account_info >>student_number(PK) >>student_username >>student_password >table: student_info >>student_number(PK) >>student_name >>student_course >>student_year >>student_section 或者我失踪了什么?

标签: mysql sql database database-design database-normalization


【解决方案1】:

好吧,如果您对规范化有疑问,您可能应该阅读该主题,然后提出具体问题。那就是……

我在这里看到的关于您的架构的唯一未规范化的是 student_subject_1、student_subject_2 等。第一范式的规则之一是“没有重复组”。也就是说,您不会在程序中使用数组或列表。任何时候开始对字段进行编号时,都应该退后一步,询问这是否不是重复组,即数组。

按规范规范化的做法是将其更改为:

student_number
subject_index
subject_name

那么主键就是 student_number + subject_index。或者,您可以创建一个合成 id,例如序列号。

然后您为每个主题创建一个记录,并使用索引来区分它们。

如果订单没有任何意义——如果 #2 也可以放在 #3 和 #4 的 #1 等处——那么我很可能会创建一个简单的序列的 student_subject_id号码。

这样做有很多充分的理由。

  1. 10 个科目是永远不可能改变的绝对限制吗?如果没有,如果有一天有一个有 11 个科目的学生出现,那么你的程序就会中断。我曾经在一个系统中遇到过这个问题,我认为它是“孩子”的 8 个插槽。我想有人会说,“谁会有超过 8 个孩子?”然后当然还有一个有 11 个孩子的人。

  2. 假设您要搜索所有正在学习某个科目的学生,例如“数据库 101”。每条记录一个主题,这是一个简单的查询:

    从 student_subject 中选择 student_number,其中 subject = 'Database 101'

(也许您想加入 student_info 表以获取他的姓名等信息,但这在这里并不重要。)

但是每条记录有 10 个主题,你必须写:

select student_number from student_subject where subject_1 = 'Database 101'
  or subject_2 = 'Database 101'
  or subject_3 = 'Database 101'
  or subject_4 = 'Database 101'
  or subject_5 = 'Database 101'
  or subject_6 = 'Database 101'
  or subject_7 = 'Database 101'
  or subject_8 = 'Database 101'
  or subject_9 = 'Database 101'
  or subject_10 = 'Database 101'

不仅要输入很多内容,而且现在输入错误的几率是原来的 10 倍。测试将不太可靠。假设您在 subject_7 的测试中输入了错误的主题名称。该程序似乎可以工作:它会找到具有该科目 1、2、3 等的学生,如果碰巧在您的测试中没有学生将此特定科目作为#7,则该程序将给出正确的结果。我曾经遇到过这种情况:有人用 category_1、category_2 等记录(我们正在将技术图书馆中的书籍分类),然后写了一个查询,其中他在 category_7 的测试中输入错误。在我们的测试中,我们通常只在每本书上放置 2 或 3 个类别,所以这一切似乎都有效。然后我们开始制作,然后,当有人第一次拥有一本包含 7 个类别的书时,它失败了。

  1. 如果您必须编写这些查询来检查所有 10 个字段,那么如果有一天您需要添加一个字段,您必须找到每个查询并更新以测试 #11。如果您错过了一个,您将开始在程序中遇到细微的错误。哦,我也遇到过一次,有点。我们有一个数据库,我认为它是 5,有人写了一个查询,他错误地测试了 1、2、4 和 5,只是忘记了测试 #3。

  2. 如果您希望能够搜索主题,则需要 10 个字段而不是 1 个字段的索引。更多的数据库开销。

如果我再想一想,可能还有其他原因。

【讨论】:

    【解决方案2】:

    有一件事我想与 Jay 关于标准化的回答区分开来……为学生和科目分成两张表。

    无需复制班级名称,它是每个学生一遍又一遍的课程,它也应该是一次,然后是每个学生和所学课程的桥梁(或链接)表。从这张表中,您还可以看到通过/失败/等级/撤回等状态...甚至是所学的学期等。

    另外,pk/fk 列我尝试始终使用“ID”而不是“_number”作为后缀,这可能会让某些人更加困惑

    Table Courses
    courseID  (PK) - auto-increment
    course    ex: ENGLISH, SCIENCE, COMPUTERS (or their abbreviated codes ENG-101, SCI-210, CMP-101)
    Other     any other description about the individual class -- REGARDLESS of when it was offered
    
    
    Table StudentCourses
    studentcourseid  (PK)
    student_number   (FK to student table)
    courseID         (FK to course table)
    enrollStatus     (enrolled, withdrawn, excused, whatever)
    enrollSemester   (ex: SPRING2014, SUMMER2014, but this too could be a lookup table of semesters)
    creditHoursEarned  (such as for computing GPA)
    

    这实际上是我在 90 年代中期写的实际大学招生系统的一个非常简短的简化,并在我离开组织时一直运行到大约 2005 年。

    【讨论】:

    • 人们在规范化方面遇到这么多麻烦的原因之一是大多数人将其与数据库设计的其他方面混淆了。规范化与列名是否以“number”或“id”结尾无关。规范化与创建不在原始表中的新属性无关(如“courseID”、“studentcourseid”、“enrollStatus”、“enrollSemester”和“creditHoursEarned”)。
    • @MikeSherrill'CatRecall',我同意你所说的“ID”与“Number”,但我只是想从 Jay 所呈现的内容中再分解一个层次。我认为我不需要重申他回答的内容。
    • RE 分离出课程表:是的,这绝对正确。我没有进入那个,因为我的答案已经很长了。请注意,关于一个主题的信息可能不仅仅是其名称或目录号:它可能与某个部门相关联,有描述、讲师和房间分配等。如果是这样,您不想为每个人都重复此信息学生上课。您想记录一次并指向那里。
    • @Jay,是的,不是的。该课程本身对整个机构都是通用的。在我编写的系统中,我有另一个 CourseOfferings 表,其中包含 courseID、teacherID、semesterID、room、building 和其他适用于每个时间的杂项。您可以在一天内开设 4 次相同的课程,由不同的讲师授课,但基础课程、目标、类别(英语、科学等)是相同的。
    • @DRapp 当然。我从未构建过课程管理系统,但我猜您通常会有一个包含课程名称、部门、描述等内容的课程表;然后是一个包含时间、房间、讲师的课程设置表。也许另一个表格将特定学位所需的课程联系在一起。一张可用教室的桌子。教官一桌。等等。
    【解决方案3】:

    规范化重新排列基础关系和连接依赖关系。 (一些连接依赖对应于函数依赖,确定候选键。)我们还可以在规范化的同时重新排列包含依赖。 (候选键和包含依赖决定外键。)因此学习“连接依赖”、“功能依赖”和“候选键”的含义。对于您的 ps,“包含依赖项”。然后向我们提供您适用的 JD、FD 和 CK(和 IND)。否则你的问题是无法回答的。

    @others:规范化涉及重新排列模式,因此唯一的 JD 是 CK 的结果。 (非正式地,摆脱基本成员条件/含义中的所有连词,而不是“attribute = foo(key)”形式。)(另外,PK没有正式的关系角色。)所以数字后缀属性的猜测含义有与规范化无关,尽管由于其他原因它是糟糕的设计(正如 Mike Sherrill 'Cat Recall' 所说)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-21
      • 2018-02-07
      • 2016-11-18
      • 2012-10-08
      • 2012-06-21
      相关资源
      最近更新 更多