用数据库中的备注表示选择的理想方式

时间:2016-10-18 12:41:33

标签: mysql database database-design database-normalization

我没有办法描述我的困境,但我说我必须"评分"成绩为A, B, C的主题,我需要为每个成绩提供评论。

每个主题分为X个类别,其中Y个主题需要"等级"和备注。

| Topic 1    | A | B | C | Remarks |
|------------|---|---|---|---------|
| Subtopic A |   |   |   |         |
| Subtopic B |   |   |   |         |
|------------|---|---|---|---------|
| Topic 2    | A | B | C | Remarks |
|------------|---|---|---|---------|
| Subtopic A |   |   |   |         |
| Subtopic B |   |   |   |         |
| Subtopic C |   |   |   |         |
| Subtopic D |   |   |   |         |

范围:

  • 所有子主题都是可选的
  • 如果回答了子主题等级,则需要备注

限制:

  • 我只限于非Barracuda MySQL环境,我打算为每个评论分配2048个字节

仅限SQL伪代码,不介意是否有错误

计划A:

只需为存储子主题名称,等级和评论的每个主题做一个表格,即

TABLE topic_1 (
    id AUTO_INCREMENT UNIQUE PRIMARY KEY,
    subtopic_a ENUM('A', 'B', 'C') NULL,
    remarks_subtopic_a VARCHAR(2048) NULL,
    subtopic_b ENUM('A', 'B', 'C') NULL,
    remarks_subtopic_a VARCHAR(2048) NULL
) ENGINE=INNODB DEFAULT CHARSET=utf8;

但这很糟糕,因为等级没有在一个地方宣布。

B计划:

为所有子主题创建表,其名称是硬编码的,但引用在另一个表中声明的等级。所有备注都按主题和资源限制分发到其他表:

INSERT INTO grades (grade)
VALUES ("A"), ("B"), ("C"); 

TABLE topics (
    id AUTO_INCREMENT UNIQUE PRIMARY KEY,
    topic_1_subtopic_a INT UNSIGNED NULL,
    FOREIGN KEY (topic_1_subtopic_a)
        REFERENCES grades(id)
        ON DELETE CASCADE
        ON UPDATE CASCADE,
    topic_1_subtopic_b INT UNSIGNED NULL,
    FOREIGN KEY (topic_1_subtopic_a)
        REFERENCES grades(id)
        ON DELETE CASCADE
        ON UPDATE CASCADE,
    topic_2_subtopic_a INT UNSIGNED NULL,
    FOREIGN KEY (topic_1_subtopic_a)
        REFERENCES grades(id)
        ON DELETE CASCADE
        ON UPDATE CASCADE,

    ...

) ENGINE=INNODB DEFAULT CHARSET=utf8;

TABLE remarks_topic_1 (
    id AUTO_INCREMENT UNIQUE PRIMARY KEY,
    subtopic_a VARCHAR(2048) NULL, 
    subtopic_b VARCHAR(2048) NULL
) ENGINE=INNODB DEFAULT CHARSET=utf8;

TABLE remarks_topic_2 (
    id AUTO_INCREMENT UNIQUE PRIMARY KEY,
    subtopic_a VARCHAR(2048) NULL, 
    subtopic_b VARCHAR(2048) NULL
    subtopic_c VARCHAR(2048) NULL, 
    subtopic_d VARCHAR(2048) NULL
) ENGINE=INNODB DEFAULT CHARSET=utf8;

计划C:

由于我们有一个子主题模式具有以下属性:

  • supertopic
  • 等级
  • 备注

为此制作一个表格,其中主题数量的合同及其各自的子主题只是"汇编"并且在前端知道;在后端,它们都只被视为subtopic数据库对象:

INSERT INTO grades (grade)
VALUES ("A"), ("B"), ("C"); 

TABLE subtopics (
    id AUTO_INCREMENT UNIQUE PRIMARY KEY,
    topic VARCHAR(100) NULL,
    subtopic INT UNSIGNED NULL,
    FOREIGN KEY (grades)
        REFERENCES grades(id)
        ON DELETE CASCADE
        ON UPDATE CASCADE,
    remarks VARCHAR(2048) NULL
) ENGINE=INNODB DEFAULT CHARSET=utf8;

PROs:

  • 广义模式
  • grades在数据库中定义
  • 在给定subtopic
  • 的情况下,存储一个已完成的remarks并不困难

CONs:

  • 前端只知道合同/业务逻辑
  • 主题和子主题不是硬编码的

Plan C是一个好的开始方式吗?或者有更好的方法来解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

是的,计划C是更好的设计,因为它更加规范化和可扩展。这是建模RDBMS的有用方法。您还可以将“主题”列外部化为单独的表,或者可以在同一个表中具有父子关系,以便您可以更轻松地管理主题。否则主题将在所有子主题中重复,如果将来有任何更改,您可能必须更新所有行。

所有其他提到的方法都存在一些可伸缩性和可维护性问题。