2015-07-11 106 views
1

我是數據庫設計的初學者。所以我有兩個表來實現多項選擇,其中一個名爲MC,持有問題,MC_choice,持有每個問題的選擇。所以MC_choice有一個外鍵約束參考MC。到現在爲止還挺好。表之間的外鍵交叉引用

在我的第一次迭代中,我用一個布爾列在MC_choice表中存儲了正確的選擇。然後我想,嗯,有一些冗餘和潛在的更新異常,並且由於哪個選擇是正確的,在功能上取決於問題本身,因此我將在MC表中存儲正確的選擇。

因此,我在MC表中添加了一個字段,該字段是一個限制指向MC_choice的外鍵。但是現在,插入新的選擇或問題變得非常困難,因爲這兩個現在像遞歸約束一樣。我正在使用Rails,並且作爲初學者,我覺得這種模式設計讓我的生活變得非常困難。

1)如果我想堅持這個遞歸的外鍵引用,我該如何保存到數據庫?
2)這個設計是否有意義?我覺得功能依賴性爭論不休,但在實踐中似乎非常麻煩。
3)ActiveRecord in Rails支持這種操作嗎?
4)如果上述模式只是愚蠢的,我應該如何設計我的表?

回答

1

你濫用「功能依賴」。這適用於一個表內的列集。你的意思是一個問題的正確答案是這個問題的一個函數。

這種情況確實只是「喜歡」「遞歸」。 FK表參考中有一個循環。但這並不是定義 FKs在彼此的方面,所以沒有遞歸。我們可以說這兩個表格相互或同時受到限制。或者更清楚的是,一些約束約束了兩個表。 (可表示爲兩個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]) 

由於的表的會員資格,是對自然的會員標準JOIN表的,

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

1)如果我想堅持這個遞歸的外鍵引用,我該如何保存到數據庫?

在SQL中,如果一個聲明的FK子行有一些NULL列(還有其他模式是這樣的),那麼DBMS認爲約束滿足。所以讓MC的援助是可以空的。首先用NULL幫助插入MC qid,然後將qid和aid插入到MC_choice中,然後將MC NULL更改爲qid的MC_choice幫助。

但是在典型的SQL DBMS中,您不能有FK週期。 (沒有理由。)如果你的意思是你想要這些表中的那些列,那麼你可以放棄一個FK聲明,但添加觸發器。 SQL DBMS僅提供少量聲明性約束表單;一般來說,還必須使用觸發器來表達約束條件。

2)這種設計是否有意義?我覺得功能依賴性爭論不休,但在實踐中似乎非常麻煩。

這很麻煩,但事實上,正確的答案是其問題的功能並不意味着答案必須在任何特定的表格與他們的問題。

3)ActiveRecord in Rails支持這種操作嗎?

是。使MC模型(表格)輔助字段(列)可以爲空。

4)如果上面的模式是愚蠢的,我應該如何設計我的表?

這裏沒有最好的和愚蠢之間的部分失地,即繁瑣並不意味着愚蠢,但只要使用上述設計,或此變體:

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

總是試圖找出最簡單的表謂詞 (成員資格標準,句子模板,填充 - [ - 命名 - ]空白語句),你可以描述你的情況。你可能想收集幾個表到一個表,但功能關係去往哪裏可能有多個選擇。

+0

這是一個很好的答案。從經歷和思考中學到了很多東西。如果可能的話,會給你超過1個upvote。 – Victor

0

假設你的目標是保持選擇題答案和他們在數據庫中,我可能會做這樣的事情:

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 

當插入一個新的問題,與nullQuestion_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)