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

Ideal way to represent choices with remarks in database

我无法描述我的困境,但我说我必须 "grade" 一个等级为 A, B, C 的主题,我需要为每个主题提供评论。

每个主题分为 X 个类别,Y 个主题需要 "grade" 和备注。

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

范围:

限制:


(SQL 伪代码而已,如有错误请勿介意)

方案A:

只需为每个主题做一个table,存储子主题名称、等级和备注,即

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计划:

为所有子主题创建 table,它们的名称是硬编码的,但引用了另一个 table 中声明的成绩。所有评论均按主题和资源限制分发给其他 table:

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:

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

为此制作一个table,其中contract的主题数量及其各自的子主题只有"assembled"并且在前端已知;在后端,它们都只被视为 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;

优点:

缺点:


C 计划是一个好的开始方式吗?或者有更好的方法来处理这个问题吗?

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

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