【问题标题】:database design for quiz with different languages不同语言测验的数据库设计
【发布时间】:2018-12-03 23:48:27
【问题描述】:

我正在尝试做一个支持多种语言的测验。我已经为测验和用户结果创建了数据库架构,但不确定如何以一种好的方式实现对不同语言的支持。

这是现在的样子(请随时指出设计错误):

* User:
   - id          PK
   - name
   - email
   - password

* Quiz
   - id          PK
   - slug
   - title

* Question
   - id          PK
   - quiz_id     FK
   - question
   - image
   - message

* Option
   - id           PK
   - question_id  FK
   - option
   - is_right

Relation between user and quiz to store results:

* Result
   - id           PK
   - user_id      FK
   - quiz_id      FK

* Result Details
   - id           PK
   - result_id    FK
   - question_id  FK
   - option_id    FK (The option user choose)
   - is_right

相同的数据库设计但表之间的连接清晰:

我的第一个想法是给测验表做一个父语言表(语言表有很多测验):

* Language:
   - id          PK
   - language_title

* Quiz
   - id           PK
   - language_id  FK
   - slug
   - title

但这只会创建一个语言类别,管理员必须为不同的语言创建一个全新的测验,而不仅仅是添加新的问题文本和选项文本。

如何为多种语言设计测验数据库,以便只有带有文本(标题、消息、问题和选​​项)的列必须获取新记录,而不必创建全新的测验?

【问题讨论】:

    标签: mysql sql database-design relational-database


    【解决方案1】:

    数据库设计应该遵循从概念信息模型派生的更一般的信息设计模型,最好是以 UML 类图的形式(因为它们的表现力)。以下是您的问题的概念信息模型:

    这样的模型仍然需要用合适的标准标识符属性和数据类型来丰富,以获得信息设计模型。通过消除关联和组合(用引用属性替换它们),我们得到以下OO类模型,可以作为Java/C#/PHP/等编码的基础。类:

    请注意,我们在此 OO 类模型中添加了对多语言测验的支持,方法是添加一个 IsoLanguageCode 枚举和一个 TextItem 类,该类具有由文本项 ID 和语言代码组成的两部分主键,以便测验,问题和答案选项使用文本项 ID 来引用用作标题、问题文本和答案文本的文本项。另请注意,Quiz 类有一个派生属性 \availableLanguages,可以在查询的帮助下计算该属性,该查询检索所有语言的所有语言,这些语言的所有问题的文本项及其所有答案选项都可用。

    可以通过将引用属性替换为相应的外键属性,从这样的 OO 类模型派生 SQL 数据库设计模型:

    【讨论】:

      【解决方案2】:

      我会建议这条一般路线:

      1) 创建一个包含字段 language_id、string_id、value 的表(翻译?)。无论语言如何,每个 string_id 都对应一个特定的消息。因此,所有 string_ids x 所有 language_ids = 不同翻译的所有可能消息。因此,(language_id,string_id) 是 PK,value 是您的测验者应该看到的。

      2) 用 string_id 替换表格上的每个文本字段。

      3) 当您的演示环境必须显示 string_id 时,它将从 1) 中提到的表中选择它,其中 language_id=您的测验者选择的那个

      【讨论】:

        【解决方案3】:

        首先,您应该检查您选择的键。您当前的设计(原子代理键无处不在)允许在所有地方出现不一致。除非您有其他未提及的多表约束,否则您可以例如有一个属于测验 B 的问题 A 的 Result_detail,但有一个属于测验 D 的问题 C 的选项以及属于测验 E 的结果。

        除非您有其他未提及的键,否则您的设计允许实际重复。你可以例如除了 id 之外,有两个相同的 Result_details,这似乎意味着有问题的用户在同一个结果中回答了同一个问题两次。让用户多次参加同一个测验可能是一项功能,但您可能不希望在同一个测验结果中对同一个问题有多个相同(或不同)的答案。这实际上是一个很好的例子,说明在某些情况下不加批判地引入代理键完全忽略了键的意义。

        Result_details.Is_right 显得多余。你能有一个正确的 Result_detail ,即使它的 Option 不是吗?

        还有其他问题,但要解决您的主要问题:如果您有固定数量的语言(特别是如果所有问题和选项都有所有语言的字符串),您可以为每个添加问题和选项列语言。如果有人对第一范式大喊大叫,请忽略他们(或要求他们正式定义 1NF)。

        如果您的语言数量不限,请将“问题”和“选项”列移到单独的表中,同时将“语言”列和外键分别移到“问题”和“选项”表中。使用例如ISO 639 用于 Language 列的值;这样您就不一定需要语言表。

        【讨论】:

        • 非常感谢您的回答!我不知道会有多少种语言,所以我必须有很多动态的。尝试按照您的指示进行操作,最终得到了这个 link 。看起来对吗?
        • 当我设计结果连接时感觉很糟糕,所以我对有很多错误并不感到惊讶。尝试重新设计它并最终得到this。还是那么糟糕吗?答案表中列的原因:user_id: 将用户连接到答案。 question_id:回答了什么问题。 option_id: 用户在问题上选择的选项。 language_used: 知道用什么语言显示结果。
        • 语言字符串表的形状是正确的,但您仍然会受到在每个表中添加整数 id 列的坏习惯的阻碍。那是不是好的设计实践。有时这样的代理 id 很有用,但在您的大多数表中,它们是禁忌的,从而使您的数据库容易出现冗余和不一致。例如,您几乎肯定会希望将每个问题限制为每种语言最多一个问题文本。也就是说Questions_t的key应该是Questions和Languages的key的组合(并集)。
        猜你喜欢
        • 2013-12-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多