好的,让我们看看你的 2NF 尝试:
学生
学生证 | 学生姓名 | 课程代码 | 模组代码 | 结果代码
课程
课程代码 | 课程名称
模块
模组代码 | 模组标题 | 学分
让我们先谈谈学生。
您的键不能是 studentID,因为 resultCode 取决于 studentID 和 courseCode(每门课程都有一个结果)。但是您的 studentName 仅取决于 studentID,因此是键的一部分(studentID,courseCode)。所以违反了2NF。你需要做这样的事情:
学生
学生证 | 学生姓名 | 课程代码 | 模组代码
课程
课程代码 | 课程名称
模块
模组代码 | 模组标题 | 学分
结果
学生证 | 课程代码 | 结果代码
但请记住,这尊重 2NF,但似乎仍然不正确,因为模块和课程现在完全不相关。所以试试这个:
学生
学生证 | 学生姓名 | 模组代码
模块
模组代码 | 模组标题 | 学分
课程
课程代码 | 课程名称 | 模组代码
结果
学生证 | 课程代码 | 结果代码
从我的角度来看,课程属于一个模块(一个模块有很多课程)。这在 2NF 中是自动的(因为键始终只是一个属性(结果除外,但只有一个非键属性始终取决于两个键属性),因此没有什么可以依赖于键的“部分” )。它也在 3NF 中,因为每个“物理”实体在数据模型中都有它的逻辑表示(更多的是经验法则而不是形式主义)。
现在让我们看看你的 3NF 尝试。我认为你的模块<->课程依赖是错误的,但让我们专注于规范化。
学生
学生证 | 学生姓名 | 科目编号
课程
课程代码 | 课程名称
模块
模组代码 | 模组标题 | 学分 | 科目编号
结果
学生证 | 模组代码 | 结果代码
这是正确的 3NF,因为除了密钥本身之外没有其他候选密钥。所以不能有任何传递依赖。
为了澄清这一点:关键候选者是许多最小的可能密钥集之一。在您的关系中,您至少找到了一个具有一个元素的关键候选对象(结果关系除外)。因此,任何其他关键候选人都不能有多个元素。这意味着,您可以简单地查看每个属性并决定“这是否可以是键?” 在您的示例中,您发现没有其他属性可以成为键-因此它自动出现在 2NF 和 3NF 中。