假設有一個要開發一個試題系統,全是不定項選擇題。一道題可能有2,3,4...個答案,數據應如何設計呢?本處旨在說明問題所在,例如同類問題還有存儲電話,一我的可能有多個號碼等等。javascript
反模式:建立多個列。html
咱們知道每列最好只存儲一個值,所以先看以下設計:java
CREATE TABLE Question( QuestionId int PK, QuestionBody nvarchar(500), Answer1 nvarchar(500), Answer2 nvarchar(500), Answer3 nvarchar(500), Answer4 nvarchar(500) )
相似上面的設計,假設答案只有兩個,那麼後面的兩個Answer3,Answer4就爲NULL,展現表以下:git
這是很傳統的屬性設計,致使即便如今很簡單的任務也變得很簡單了!數據庫
一、查詢數據數據庫設計
假設有一道題的答案出錯了,可是你只記得答案。post
SELECT * FROM Question WHERE Answer1 = '豬有4條腿' OR Answer2 = '豬有4條腿' OR Answer3 = '豬有4條腿' OR Answer4 = '豬有4條腿'
顯示結果以下:this
假如,另外也有一道題目,也有一個答案豬有3條腿,那麼你要查得這條數據,就須要這樣:spa
SELECT * FROM Question WHERE (Answer1 = '豬有4條腿' OR Answer2 = '豬有4條腿' OR Answer3 = '豬有4條腿' OR Answer4 = '豬有4條腿') AND (Answer1 = '豬有3條腿' OR Answer2 = '豬有3條腿' OR Answer3 = '豬有3條腿' OR Answer4 = '豬有3條腿')
怎麼樣又長又臭吧!不怕,哥安慰下你,其實有簡單點的方法:設計
SELECT * FROM Question WHERE '豬有3條腿' IN (Answer1,Answer2,Answer3,Answer4) AND '豬有4條腿' IN (Answer1,Answer2,Answer3,Answer4)
怎麼樣短了不少吧,相信你也仍是不會賣賬。
二、添加、更新以及刪除值
在以上設計中,假設我要刪除答案'豬有3條腿'的SQL語句怎麼寫呢?你們被考到了吧。
UPDATE Question SET Answer1 = NULLIF(Answer1,'豬有3條腿'), Answer2 = NULLIF(Answer2,'豬有3條腿'), Answer3 = NULLIF(Answer3,'豬有3條腿'), Answer4 = NULLIF(Answer4,'豬有5條腿') WHERE QuestionId = 2
添加一個答案,更新一個答案都有點難寫, 有興趣的朋友能夠本身敲敲。
三、確保惟一性
如何確保同一個值不出如今多個列中,即有可能你並不想一道題中有兩個答案是同樣的。咱們很難阻止重複的答案出現,由於Unique只能用於行。
四、值在不斷增加
當咱們有一道題有5個答案的時候,悲劇,你要更改表結構了。
以上種種問題說明,以上設計根本不堪一擊。
問題的根源在於:存儲一個具備多個值的屬性。對於以上設計,若是每道題都規定是4個答案,以上設計是能夠用的。問題在於,答案個數不肯定。
所以,咱們須要建立一個從屬表,將不肯定個數的值提取出來做爲行存儲,而不是列。
整體設計以下:
CREATE TABLE Question( QuestionId int PK, QuestionBody Body nvarchar(500) ) CREATE TABLE Answer( AnswerId int PK, AnswerBody nvarchar(500), QuestionId int, FOREIGN KEY(QuestionId) REFERENCES Question(QuestionId) )
對於以上設計,多少個答案都沒問題了,並且增刪查改都簡單了不止一個檔次。
其實,只不過是一個一對多的關係。並且這個問題很容易一眼就看出,不過變種問題你卻未必會條件反應式地提出同樣從屬表。