第一范式

1,表中所有字段只具有单一属性;address既包含了省市区 河南-郑州-高新区 2,单一属性的列由基本的数据类型构成; 3,设计出的表为二维表;

第二范式

要求一个表中只具有一个业务主键;即符合第二范式的表中不能存在非主键列只对部分主键的依赖关系,(业务主键可能包含一个列或多个列)。通常表现在复合主键的情况下,部分字段,不依赖复合主键中的某一个

  1. 以电商网站示例
  2. 1,商品管理功能
  3. 修改前==> 商品信息表(商品名称、商品分类名称、商品描述、商品价格)
  4. 业务主键(商品名称、商品分类名称)
  5. 此时如何做到新增分类;(而商品后续添加)
  6. 修改后==> 商品信息(商品名称、商品描述、商品价格等)
  7. 分类信息(商品分类名称,分类描述)
  8. 商品分类关系表(商品名称、商品分类名称)
  9. goods | CREATE TABLE `goods` (
  10. `g_name` varchar(20) DEFAULT NULL,
  11. `g_desc` varchar(100) DEFAULT NULL,
  12. `g_price` decimal(10,3) DEFAULT NULL,
  13. `g_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  14. PRIMARY KEY (`g_id`)
  15. ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 |
  16. category | CREATE TABLE `category` (
  17. `c_name` varchar(20) DEFAULT NULL,
  18. `c_desc` varchar(100) DEFAULT NULL,
  19. `c_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  20. PRIMARY KEY (`c_id`)
  21. ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 |
  22. gcrelation | create table gcrelation(g_id int unsigned,c_id int unsigned,
  23. foreign key(g_id) references goods(g_id),
  24. foreign key(c_id) references category(c_id));
  25. -------------------------------------------------------------
  26. a,删除商品 商品分类关系表得删除
  27. a-1,先删除中间表,再删除商品表
  28. b,删除分类
  29. 同上
  30. c,增加
  31. 先增加商品或分类,再增加关联关系
  32. d,修改
  33. 只修改商品表、分类表,不牵扯到中间表
  34. e,查
  35. e-1,某分类下的所有商品
  36. select a.* from goods a left join gcrelation b on a.g_id = b.g_id where b.c_id = 1;
  37. select * from goods where g_id in (select g_id from gcrelation where c_id = 1);
  38. e-2,各个分类下有多少商品
  39. select count(b.c_id),a.c_name,a.c_id,b.c_id from category a left join gcrelation b on a.c_id = b.c_id group by a.c_id;
  40. e-3,查询所有的商品既所属的分类信息
  41. select a.g_name,a.g_price,c_name from goods a left join gcrelation b on a.g_id = b.g_id left join category c on b.c_id = c.c_id;
  42. 反范式设计:
  43. 冗余有时是必要的。
  44. 将中间表商品分类关系表移除,将商品分类名称(分类ID)添加至商品信息表,商品分类ID,作为商品表对分类表的外键
  45. note :关系由谁来维护
  46. 一般的情况下-> 关系在多的一端进行维护

第三范式

每一个非主属性既不部分依赖于也不传递依赖于业务主键,即在第二范式的基础上消除了非主属性对主键的传递依赖、

比如学生信息表 sno,sname,birth_date,depart_name,depart_addr,depart_tel (sno为primary key) sno 得到学生所在的院系depart_name, depart_name可以得到depart_addr,depart_tel等信息 得将学生信息表拆分为两张表 2,订单相关功能 修改前==> 订单表(订单编号[primarykey],用户名,订单日期,订单金额,订单商品分类,订单商品名,订单商品单价, 订单商品数量,支付金额,物流单号) 此时订单编号 -> 订单商品->订单商品数量->订单商品单价,订单金额 不符合第三范式 修改后==> 订单表a(订单编号,用户名,订单日期,支付金额,物流单号) 订单商品关联表b(订单编号,订单商品名称,订单商品分类名称,订单数量) 商品信息表d(商品名称、商品分类名称、商品描述、商品价格) 商品分类关联表c 需求一,计算用户订单总金额(关联表越多,性能越差) select 用户名,sum(d.订单商品单价*b.订单商品数量) from 订单表 a join 订单商品关联表 b on a.订单编号 = b.订单编号 join on 商品分类关联表 c on c.商品名称 = b.商品名称 and c.分类名称 = b.订单商品分类名称 join 商品信息表 d on d.商品名称 = c.商品名称 group by 订单用户 问题,双11促销,价格波动,得重新进行价格关联,而且还要记录历史价格 需求二,查询下单用户和订单详情 还得关联用户信息表 此时都已经涉及了5张表 反范式设计: 订单表中添加用户信息比如(手机号[用户的任何凭证],订单金额) -> 方便直接查询订单用户信息 订单商品关联表添加商品表中的(商品单价信息) 反范式后的需求一: select 用户凭证信息,sum(订单金额) from 订单表 group by 用户凭证


    3,层级类型树表的处理
        部门表
        权限表
        菜单表


        book表
            name,p_id(父级目录)
        -----------------------------------------------------------------
        |    CREATE TABLE `books` (
            `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
            `name` varchar(20) DEFAULT NULL,
            `p_id` int(10) unsigned DEFAULT NULL COMMENT '上级目录',
            PRIMARY KEY (`id`)
            ) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8 |
        ------+-------+-------------------------------------------------


        书籍信息
            书名
                章节名
                    小节
                        标题
            MySQL
                初始MySQl
                    MySQL的安装
                        windows的安装
                        linux的安装
                MySQL语法
                    insert的使用
                    select的使用
            Java        


mysql> 
        SELECT
          a.name AS ONE,
          b.name AS two,
          c.name AS three,
          d.name AS four
        FROM
          books a
          LEFT JOIN books b
            ON a.id = b.p_id
          LEFT JOIN books c
            ON b.id = c.p_id
          LEFT JOIN books d
            ON c.id = d.p_id
        WHERE a.p_id = 0;


+----------------+-----------+--------------+---------------+
| one            | two       | three        | four          |
+----------------+-----------+--------------+---------------+
| MySQL          | 初识MySQL | MySQL的安装  | windows的安装 |
| MySQL          | 初识MySQL | MySQL的安装  | linux的安装   |
| MySQL          | MySQL语法 | insert的使用 | NULL          |
| MySQL          | MySQL语法 | select的使用 | NULL          |
| ThinkingInJava | NULL      | NULL         | NULL          |
+----------------+-----------+--------------+---------------+
5 rows in set (0.00 sec)