zoukankan      html  css  js  c++  java
  • 逻辑数据库设计

      假设有一个要开发一个试题系统,全是不定项选择题。一道题可能有2,3,4...个答案,数据应如何设计呢?本处旨在说明问题所在,例如同类问题还有存储电话,一个人可能有多个号码等等。

    一、存储多值属性

      反模式:创建多个列。

      我们知道每列最好只存储一个值,因此先看如下设计:

      CREATE TABLE Question(
          QuestionId int   PK,
          QuestionBody nvarchar(500),
          Answer1  nvarchar(500),
          Answer2  nvarchar(500),
          Answer3  nvarchar(500),
          Answer4  nvarchar(500)
      )

      类似上面的设计,假设答案只有两个,那么后面的两个Answer3,Answer4就为NULL,展示表如下:

      

      这是很传统的属性设计,导致即使现在很简单的任务也变得很简单了!

      1、查询数据

      假设有一道题的答案出错了,但是你只记得答案。

    SELECT * FROM Question WHERE 
        Answer1 = '猪有4条腿'
        OR Answer2 = '猪有4条腿'
        OR Answer3 = '猪有4条腿'
        OR Answer4 = '猪有4条腿'

      显示结果如下:

      

      假如,另外也有一道题目,也有一个答案猪有3条腿,那么你要查得这条数据,就需要这样:

    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)

      怎么样短了很多吧,相信你也还是不会卖帐。

      2、添加、更新以及删除值

      在以上设计中,假设我要删除答案'猪有3条腿'的SQL语句怎么写呢?大家被考到了吧。

      UPDATE Question
          SET Answer1 = NULLIF(Answer1,'猪有3条腿'),
              Answer2 = NULLIF(Answer2,'猪有3条腿'),
              Answer3 = NULLIF(Answer3,'猪有3条腿'),
              Answer4 = NULLIF(Answer4,'猪有5条腿')
      WHERE QuestionId = 2

      添加一个答案,更新一个答案都有点难写, 有兴趣的朋友可以自己敲敲。

      3、确保唯一性

      如何确保同一个值不出现在多个列中,即有可能你并不想一道题中有两个答案是一样的。我们很难阻止重复的答案出现,因为Unique只能用于行。

      4、值在不断增长

      当我们有一道题有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)
    )

      对于以上设计,多少个答案都没问题了,而且增删查改都简单了不止一个档次。

      其实,只不过是一个一对多的关系。而且这个问题很容易一眼就看出,不过变种问题你却未必会条件反应式地提出一样从属表。

  • 相关阅读:
    GC
    java基石-JVM
    golang 结构体指针及赋值
    golang 记一次map中struct的管道造成死锁的解决方式
    golang 封装"执行shell管理redis(string,集合等)"成api
    golang panic及处理
    Python简直无所不能!在电脑上如何调用手机摄像头?教你轻松搞定!
    2021最新版Python爬取抖音小姐姐短视频,无水印,超级详细!(附视频/源码)
    自从学会Python爬虫后,爬视频我只爬小姐姐!教你批量下载某短视频网站视频!
    突然不知道听什么歌了,但是排行榜的准没错,于是用Python全部都爬下来了!
  • 原文地址:https://www.cnblogs.com/kissdodog/p/3304523.html
Copyright © 2011-2022 走看看