假设有一个要开发一个试题系统,全是不定项选择题。一道题可能有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) )
对于以上设计,多少个答案都没问题了,并且增删查改都简单了不止一个档次。
其实,只不过是一个一对多的关系。并且这个问题很容易一眼就看出,不过变种问题你却未必会条件反应式地提出同样从属表。