SQL设计决策:我应该合并这些表吗?

时间:2011-05-31 22:11:40

标签: mysql sql database database-design

我正在尝试为客户设计一个小型数据库。我的客户有一个与公立和私立学校合作的组织;对于所涉及的每所学校,每所学校都有一个实施(一章)。

为了设计这个,我把两张桌子放在一起;一个用于学校,一个用于章节。但是,我不确定是否应将两者合并在一起。表格如下:

mysql> describe chapters;
+--------------------+------------------+------+-----+---------+----------------+
| Field              | Type             | Null | Key | Default | Extra          |
+--------------------+------------------+------+-----+---------+----------------+
| id                 | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| school_id          | int(10) unsigned | NO   | MUL |         |                |
| is_active          | tinyint(1)       | NO   |     | 1       |                |
| registration_date  | date             | YES  |     | NULL    |                |
| state_registration | varchar(10)      | YES  |     | NULL    |                |
| renewal_date       | date             | YES  |     | NULL    |                |
| population         | int(10) unsigned | YES  |     | NULL    |                |
+--------------------+------------------+------+-----+---------+----------------+
7 rows in set (0.01 sec)

mysql> describe schools;
+----------------------+------------------------------------+------+-----+---------+----------------+
| Field                | Type                               | Null | Key | Default | Extra          |
+----------------------+------------------------------------+------+-----+---------+----------------+
| id                   | int(10) unsigned                   | NO   | PRI | NULL    | auto_increment |
| full_name            | varchar(255)                       | NO   | MUL |         |                |
| classification       | enum('high','middle','elementary') | NO   |     |         |                |
| address              | varchar(255)                       | NO   |     |         |                |
| city                 | varchar(40)                        | NO   |     |         |                |
| state                | char(2)                            | NO   |     |         |                |
| zip                  | int(5) unsigned                    | NO   |     |         |                |
| principal_first_name | varchar(20)                        | YES  |     | NULL    |                |
| principal_last_name  | varchar(20)                        | YES  |     | NULL    |                |
| principal_email      | varchar(20)                        | YES  |     | NULL    |                |
| website              | varchar(20)                        | YES  |     | NULL    |                |
| population           | int(10) unsigned                   | YES  |     | NULL    |                |
+----------------------+------------------------------------+------+-----+---------+----------------+
12 rows in set (0.01 sec)

(请注意,这些表格不完整 - 我还没有实现外键。另外,请忽略某些字段的varchar大小,它们会发生变化。)

到目前为止,将它们分开的优点是:

  1. 对学校和学校的单独询问 章节更容易。我不知道 这是必要的,但是 很高兴能够做到。
  2. 我可以让章节无效 没有直接影响 学校信息。
  3. 数据的一般分离 - 中的字段     “章节”直接相关     章本身,而不是学校     它存在的地方。 (我喜欢     组织 - 它更有意义     对我来说。也遵循“只有关键”的口号。)
  4. 如果可能,我们可以收集学校 没有章节的数据 与之相关的,可能会产生 感觉如果我们最终想要人 选择一所学校并自动填充 数据。
  5. 缺点:

    1. 学校和学校的独立身份证 章节。据我所知,那里 只会是一对一的 两者之间的关系,所以 这样做可能会引入更多 可能导致错误的复杂性 下线(如导入数据 来自电子表格,这是不合情理的 我会做很多事情。
    2. 如果有一对一的比例,和 ID是auto_increment字段, 我猜的是chapter_id和 school_id最终会变成一样 - 所以为什么不把它们放在一张桌子里呢?
    3. 据我所知,章节 他们的身份并不是真的可以识别 自己 - 他们被绑在一所学校,并且 因此应该是a的一个子集 学校。他们真的应该吗? 表中的单独对象?
    4. 现在,我倾向于将它们分成两个独立的桌子;似乎优点胜过缺点,但我想确保我不会创造一个可能导致问题的情况。我一直与我的客户保持联系,我正在尝试获取有关他们存储的数据以及他们想要用它做什么的更多细节,我认为这将真正有所帮助。但是,我想听到消息灵通人士的一些意见;还有什么我没有想过的吗?这里的底线就是我想第一次做正确的事情。

4 个答案:

答案 0 :(得分:3)

我认为他们应该分开。但是,您可以将章节作为学校的子类型(并且学校是超类型)并使用相同的ID。在数据库中你使用SchoolID的其他地方你指的是学校和你在哪里使用ChapterID你的意思是章节。

CREATE TABLE School (
   SchoolID int unsigned NOT NULL AUTO_INCREMENT,
   CONSTRAINT PK_School PRIMARY KEY (SchoolID)
)

CREATE TABLE Chapter (
   ChapterID int unsigned NOT NULL,
      CONSTRAINT PK_Chapter PRIMARY KEY (ChapterID)
      CONSTRAINT FK_Chapter_School FOREIGN KEY (ChapterID) REFERENCES School (SchoolID)
)

现在除非有学校,否则你不能有一章。如果发生了这样的时间,你必须允许每个学校有多个章节,你将使用ChapterID作为身份/自动增量重新创建章节表,添加一个填充了相同值的SchoolID列,并将FK放在学校上,并且像以前一样继续,只将ID插入SchoolID而不是ChapterID。如果MySQL支持将显式值插入自动增量列,那么提前使其成为SchoolID自动增量可以省去以后的麻烦(除非支持将常规列切换为自动增量,在这种情况下没有问题)。

将它们分开的其他好处:

  • 您可以直接使用SchoolID或ChapterID创建外键关系,以便您存储的数据始终正确(例如,如果不存在章节,那么在创建之前您无法存储相关数据)
  • 分别查询每个表格会更好,因为行不包含无关信息。
  • 可以使用某些必需的列创建学校,但该章节未创建(暂时)。然后,在创建它时,您也可以在其中包含一些NOT NULL列。

答案 1 :(得分:1)

将它们分开。

他们目前可能是1-1 ......但是这些显然是分开的概念。

他们最终会想要输入没有章节的学校吗?也许作为销售主导系统的一部分?

每个学校真的只有一个章节,还是只有一个活跃章节?那个时间呢?他们是否有可能在x学校要求提供过去10年所有章节的报告?

答案 2 :(得分:0)

你说链接总是1比1,但学校总是有一章可以改章吗?如果是这样,那么将章节分开是一个好主意。

答案 3 :(得分:0)

将它们分开的另一个原因是,如果两个实体组合在一起的信息量会使记录的长度超过数据库后端可以处理的长度。通常构建一对一表以将需要存储在记录中的数据量保持在适当的大小。

进一步是要求公司1-1还是它有可能是1-many?如果是第二个,现在就把它作为一个单独的表。是否有可能让学校没有章节?我再次将它们分开。

你打算如何查询这些数据,你通常是否需要同一查询中关于章和学校的数据,如果你确定它不可能变成一个表,你可以将它们放在一个表中一对多的关系。但是,无论如何,索引的连接字段的正确连接应该很快。

我倾向于认为这些是独立的实体,并且会将它们保留为分离,除非存在导致将它们放在一起的严重性能问题。我认为从一开始就在单独的表中使用单独的实体往往比将它们组合在一起风险更小。只要索引是正确的,性能通常是完全可以接受的,如果你通常不需要一直查询来自两个表的数据,那么性能甚至会更好。