【问题标题】:Foreign Key Cross-Reference Between Tables表之间的外键交叉引用
【发布时间】:2015-09-30 02:16:21
【问题描述】:

我是数据库设计的初学者。所以我有两张表用于实现多项选择,一张名为MC,用于保存问题,MC_choice,用于保存每个问题的选择。所以MC_choice 有一个外键限制为引用MC。到目前为止,一切顺利。

在我的第一次迭代中,我将正确的选择存储在带有布尔列的 MC_choice 表中。然后我想,嗯,有一些冗余和潜在的更新异常,因为哪个选择是正确的在功能上取决于问题本身,我将把正确的选择存储在MC 表本身中。

所以我在MC 表中添加了一个字段,该字段是一个限制为指向MC_choice 的外键。但是现在插入新的选择或问题变得非常困难,因为这两者现在像递归约束一样。我正在使用 Rails 并且是一个初学者,我觉得这种模式设计让我的生活变得非常困难。

1)如果我要坚持这个递归外键引用,我该如何保存到数据库?
2)这个设计有意义吗?我觉得功能依赖在争论它,但在实践中似乎很麻烦。
3) Rails 中的 ActiveRecord 是否支持这种操作?
4)如果上面的模式很傻,我应该如何设计我的表?

【问题讨论】:

    标签: ruby-on-rails database activerecord database-design schema


    【解决方案1】:

    您误用了“功能依赖”。这适用于一个表中的列集。您的意思是问题的正确答案是问题的函数。

    情况确实只是“喜欢”“递归”。 FK 表引用中有一个循环。但这并没有定义 FK 之间的相互关系,因此没有递归。我们可以说这两个表是相互约束或同时约束的。或者更清楚的是,某些约束约束了两个表。 (可以表示为两个 FK 约束的合取。)

    您的情况可以通过表格和简单的行成员资格条件来描述,如下所示:

    Question(qid,text) -- question [qid] has text [text]
        key qid
    Answer(aid,text) -- answer [aid] has text [text]
        key aid
    Offers(qid,aid) -- question [qid] offers answer [aid]
        key (qid,aid)
        fk qid to Question, fk aid to Answer
    Ok(qid,aid) -- [aid] is the right answer to [qid]
        key (qid,aid)
        fk (qid,aid) to Offers
        fk qid to Question, fk aid to Answer
    

    这是一个简单的设计。碰巧没有 FK 循环。 (另外,问题和回答的 FK 不需要声明/明确,因为它们是要约的 FK 及其 FK 的后果。)

    可以通过多种方式组合这些。您选择了一些东西(具有 FK 循环),例如:

    MC(qid,text,aid)
        -- question [qid] has answer [aid]
        AND [aid] is the right answer to [qid]
    MC_choice(aid,qid,text)
        -- question [qid] offers answer [aid]
        AND answer [aid] has text [text])
    

    因为表的成员条件的 AND 是表的 NATURAL JOIN 的成员条件,

    MC = Question NATURAL JOIN Ok
    MC_choice = Offers NATURAL JOIN Answer
    

    1)如果我要坚持这个递归外键引用,如何保存到数据库中?

    在 SQL 中,如果声明的 FK 子行有一些列 NULL(还有其他模式),则 DBMS 认为约束已满足。因此,允许 MC 辅助可以为空。先插入一个带有NULLaid的MC qid,然后把qid和aid插入MC_choice,然后把MC NULL改成qid的MC_choiceaid。

    但在典型的 SQL DBMS 中,您不能有 FK 循环。 (没有充分的理由。)如果您的意思是无论如何都想要这些表中的这些列,那么您可以删除 FK 声明但添加触发器。 SQL DBMS 只提供少数声明性约束形式;一般来说,还必须使用触发器来表达约束。

    2) 这种设计有意义吗?我觉得功能依赖在争论它,但在实践中似乎很麻烦。

    这很麻烦,但正确答案是其问题的函数这一事实并不意味着答案必须与他们的问题放在任何特定的表格中。

    3) Rails 中的 ActiveRecord 是否支持这种操作?

    是的。使 MC 模型(表)辅助字段(列)可为空。

    4) 如果上面的架构很傻,我应该如何设计我的表?

    not best 和 silly 之间有一定的距离,即笨重并不意味着愚蠢,而只是使用上面的设计,或者这个变体:

    MC = Question
    MC_choice = Offers NATURAL JOIN Answer
    MC_ok = Ok
    

    始终尝试找出最简单的表谓词(成员资格标准、句子模板、填写-[命名-]空白语句),以用于描述您的情况。您可能希望将多个收集到一个表中,但对于函数关系的去向,可能有多个选择。

    【讨论】:

    • 这是一个很好的答案。从经历和思考中学到了很多东西。如果可能的话,会给你的不仅仅是 1 票。
    【解决方案2】:

    假设您的目标是在数据库中保留多项选择题及其答案,我可能会这样做:

    tblQuestions
    ------------
    Question_Id (pk)
    Question_Text
    Question_Correct_Answer (nullable, fk to tblAnswers)
    
    tblAnswers
    ----------
    Answer_Id (pk)
    Answer_Question_Id (fk to tblQuestion)
    Answer_Text 
    

    插入新问题时,将其与null 一起插入Question_Correct_Answer 列,并在插入问题的答案时填充它。
    插入的问题和答案应该在一个事务中,这样就不可能插入没有答案和正确答案 ID 的问题。

    为了保留用户选择的答案,您只需要保留答案 id (因为每个答案只属于一个问题)。

    添加一个视图以选择问题文本和答案文本以显示结果,如下所示:

    select question_text, 
           answer_text, 
           case when answer_Id = question_correct_answer then
             1
           else
             0
           end as IsCorrect
    from tblUserAnswer
    inner join tblAnswer ON(UserAnswer_Answer_Id = Answer_Id)
    inner join tblQuestion  ON(Answer_Question_Id = Question_Id)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-09
      • 2020-01-31
      • 2012-05-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多