Skip to main content
Global

4.4: 设计数据库

  • Page ID
    172456
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    设计数据库

    假设一所大学想要创建一个数据库来跟踪学生俱乐部的参与情况。 在采访了几个人之后,设计团队得知实施该系统是为了更好地了解大学如何为俱乐部提供资金。 这将通过跟踪每个俱乐部有多少会员以及俱乐部的活跃程度来实现。 球队决定系统必须跟踪俱乐部、其成员和赛事。 根据这些信息,设计团队确定需要创建以下表:

    • 俱乐部:这将跟踪俱乐部名称、俱乐部主席和俱乐部的简短描述。
    • 学生:学生姓名、电子邮件和出生年份。
    • 会员资格:此表将关联学生与俱乐部,允许我们让任何给定的学生加入多个俱乐部。
    • 活动:此表将记录俱乐部何时开会以及有多少学生参加。

    既然设计团队已经确定要创建哪些表,他们需要定义每个表将包含的具体信息。 这需要确定每个表中将出现的字段。 例如,俱乐部名称将是 “俱乐部” 表中的一个字段。 “名字” 和 “姓氏” 将是 “学生” 表中的字段。 最后,由于这将是一个关系数据库,因此每个表都应该有一个与至少一个其他表相同的字段(换句话说:它们之间应该有关系)。

    要正确创建此关系,必须为每个表选择一个主键。 此键是表中每条记录的唯一标识符。 例如,在学生表中,可以使用学生的名字来唯一地识别他们。 但是,有些学生很可能会使用姓氏(例如 Mike、Stefanie 或 Chris),因此应选择不同的字段。 学生的电子邮件地址可能是主键的不错选择,因为电子邮件地址是唯一的。 但是,主键无法更改,因此这意味着如果学生更改了他们的电子邮件地址,我们将不得不将其从数据库中删除,然后重新插入,这不是一个有吸引力的主张。 我们的解决方案是为每个学生创建一个值(用户 ID),该值将用作主键。 我们还将为每个学生俱乐部做这件事。 这个解决方案很常见,也是你有这么多用户 ID 的原因!

    你可以在下图中看到最终的数据库设计:

    Behaviorism_1.gif
    \(\PageIndex{1}\):数据设计流程。 图片由 David Bourgeois 博士提供,已获得 CC BY 4.0 的许可

    通过这种设计,我们不仅可以整理满足要求所需的所有信息,而且还成功地将所有表格关联在一起。 以下是一些示例数据的数据库表可能的样子。 请注意,会员表的唯一目的是允许我们将多个学生关联到多个俱乐部。

    Behaviorism_1.gif
    \(\PageIndex{2}\):桌子:俱乐部。 图片由 David Bourgeois 博士提供,已获得 CC BY 4.0 的许可
    Behaviorism_1.gif
    \(\PageIndex{3}\):表:学生。 图片David Bourgeois 博士提供,已获得 CC BY 4.0 的许可
    Behaviorism_1.gif
    \(\PageIndex{4}\):表:成员资格。 图片:作者:David Bourgeois,博士获得 CC BY 4.0 的许可

    正常化

    在设计数据库时,需要理解的一个重要概念是标准化。 简而言之,对数据库进行标准化意味着要以以下方式对其进行设计:

    • 减少表间数据的冗余,更易于映射
    • 取出不一致的数据。
    • 信息仅存储在一个地方。
    • 为桌子提供尽可能多的灵活性。

    在学生俱乐部数据库设计中,设计团队努力实现这些目标。 例如,要跟踪会员资格,一个简单的解决方案可能是在俱乐部表中创建一个 Members 字段,然后列出所有成员的姓名。 但是,这种设计意味着,如果一个学生加入了两个俱乐部,则必须再次输入他或她的信息。 相反,设计者通过使用两张表格解决了这个问题:学生和会员资格。

    在此设计中,当学生加入他们的第一个俱乐部时,我们必须将该学生添加到 Students 表中,在该表中输入他们的名字、姓氏、电子邮件地址和出生年份。 添加到 “学生” 表后,将生成一个学生 ID。 现在,我们将添加一个新条目来表示该学生是特定的俱乐部会员。 这是通过在会员表中添加包含学生证和俱乐部ID的记录来实现的。 如果该学生加入第二个俱乐部,我们不必重复学生的姓名、电子邮件和出生年份;相反,我们只需要在会员表中再次输入第二个俱乐部的ID和学生的ID。

    Student Clubs 数据库的设计还使更改设计变得简单,而无需对现有结构进行重大修改。 例如,如果要求设计团队向系统添加功能以跟踪分会的教师顾问,我们可以轻松地完成此操作,方法是添加教师顾问表(类似于学生表),然后在俱乐部表中添加一个新字段来存放教师顾问 ID。

    数据类型

    在定义数据库表中的字段时,我们必须为每个字段指定一个数据类型。 例如,“出生年份” 字段是年份,因此它将是一个数字,而 “名字” 将为文本。 大多数现代数据库都允许存储几种不同的数据类型。 下面列出了一些更常见的数据类型:

    • 文本:用于存储简短的非数字数据,通常少于 256 个字符。 数据库设计人员可以确定文本的最大长度。
    • 数字:用于存储数字。 通常会选择几种不同的数字类型,具体取决于最大数字的大小。
    • 是/否:数字数据类型的一种特殊形式,(通常)长度为一个字节,0 表示 “否” 或 “假”,1 表示 “是” 或 “真”。
    • 日期/时间:数字数据类型的特殊形式可以解释为数字或时间。
    • 货币:数字数据类型的一种特殊形式,它使用货币指示符和两位小数来格式化所有值。
    • 段落文本:此数据类型允许长度超过 256 个字符的文本。
    • 对象:此数据类型允许存储无法通过键盘输入的数据,例如图像或音乐文件。

    正确定义数据类型的重要性在于提高数据的完整性和正确的存储位置。 我们必须正确定义字段的数据类型,数据类型告诉数据库可以使用数据执行哪些函数。 例如,如果我们想对其中一个字段执行数学函数,则必须告诉数据库该字段是数字数据类型。 因此,如果我们有一个存储出生年份的字段,我们可以从当前年份中减去该字段中存储的数字以得出年龄。

    还必须确定为定义的数据分配存储空间。 例如,如果 “名字” 字段定义为文本 (50) 数据类型,则为我们要存储的每个名字分配五十个字符。 但是,即使名字只有五个字符长,也将分配五十个字符(字节)。 虽然这看起来可能没什么大不了的,但如果我们的表最终有 50,000 个名字,我们会分配 50 * 50,000 = 2,500,000 字节来存储这些值。 谨慎的做法是缩小田地的面积,这样我们就不会浪费存储空间。