25.3 唯一性约束(unique)

  • 唯一约束修饰的字段具有唯一性,不能重复,但可以为NULL ```sql
  • 案例:给某一列添加unique drop table if exists t_user; create table t_user( id int, username varchar(255) unique // 列级约束 ); insert into t_user values(1,’zhangsan’); insert into t_user values(2,’zhangsan’); ERROR 1062 (23000): Duplicate entry ‘zhangsan’ for key ‘username’

  • 案例:给两个列或者多个列添加unique drop table if exists t_user; create table t_user( id int, usercode varchar(255), username varchar(255), unique(usercode,username) // 多个字段联合起来添加1个约束unique 【表级约束】 );

//表级约束,比较的是两个字段的内容 111zs 111ls insert into t_user values(1,’111’,’zs’); insert into t_user values(2,’111’,’ls’); insert into t_user values(3,’222’,’zs’); select * from t_user; insert into t_user values(4,’111’,’zs’); ERROR 1062 (23000): Duplicate entry ‘111-zs’ for key ‘usercode’

drop table if exists t_user; create table t_user( id int, usercode varchar(255) unique, username varchar(255) unique ); insert into t_user values(1,’111’,’zs’); insert into t_user values(2,’111’,’ls’); ERROR 1062 (23000): Duplicate entry ‘111’ for key ‘usercode’

  • 注意:not null约束只有列级约束。没有表级约束。 ```

25.4 主键约束

  • 给一张表添加主键约束 ```sql drop table if exists t_user; create table t_user( id int primary key, // 列级约束 username varchar(255), email varchar(255) ); insert into t_user(id,username,email) values(1,’zs’,’zs@123.com’); insert into t_user(id,username,email) values(2,’ls’,’ls@123.com’); insert into t_user(id,username,email) values(3,’ww’,’ww@123.com’); select * from t_user; +——+—————+——————+ | id | username | email | +——+—————+——————+ | 1 | zs | zs@123.com | | 2 | ls | ls@123.com | | 3 | ww | ww@123.com | +——+—————+——————+

insert into t_user(id,username,email) values(1,’jack’,’jack@123.com’); ERROR 1062 (23000): Duplicate entry ‘1’ for key ‘PRIMARY’

insert into t_user(username,email) values(‘jack’,’jack@123.com’); ERROR 1364 (HY000): Field ‘id’ doesn’t have a default value

  1. - 根据以上的测试得出:id是主键,因为添加了主键约束,主键字段中的数据不能为NULL,也不能重复;主键的特点:不能为NULL,也不能重复
  2. - 主键相关的术语
  3. 主键约束 : primary key<br />主键字段 : id字段添加primary key之后,id叫做主键字段<br />主键值 : id字段中的每一个值都是主键值。
  4. - 主键有什么作用
  5. 表的设计三范式中有要求,第一范式就要求任何一张表都应该有主键;主键的作用:主键值是这行记录在这张表当中的唯一标识。(就像一个人的身份证号码一样)
  6. - 主键的分类
  7. - 根据主键字段的字段数量来划分:
  8. 单一主键(推荐的,常用的。)<br />复合主键(多个字段联合起来添加一个主键约束)(复合主键不建议使用,因为复合主键违背三范式)
  9. - 根据主键性质来划分:
  10. 自然主键:主键值最好就是一个和业务没有任何关系的自然数。(这种方式是推荐的)<br />业务主键:主键值和系统的业务挂钩,例如:拿着银行卡的卡号做主键,拿着身份证号码作为主键。(不推荐用)<br />最好不要拿着和业务挂钩的字段作为主键。因为以后的业务一旦发生改变的时候,主键值可能也需要随着发生变化,但有的时候没有办法变化,因为变化可能会导致主键值重复。<br />
  11. - 一张表的主键约束只能有1个。(必须记住)
  12. - 使用表级约束方式定义主键:
  13. ```sql
  14. drop table if exists t_user;
  15. create table t_user(
  16. id int,
  17. username varchar(255),
  18. primary key(id)
  19. );
  20. insert into t_user(id,username) values(1,'zs');
  21. insert into t_user(id,username) values(2,'ls');
  22. insert into t_user(id,username) values(3,'ws');
  23. insert into t_user(id,username) values(4,'cs');
  24. select * from t_user;
  25. insert into t_user(id,username) values(4,'cx');
  26. ERROR 1062 (23000): Duplicate entry '4' for key 'PRIMARY'
  27. 以下内容是演示以下复合主键,不需要掌握:
  28. drop table if exists t_user;
  29. create table t_user(
  30. id int,
  31. username varchar(255),
  32. password varchar(255),
  33. primary key(id,username)
  34. );
  • mysql提供主键值自增:(非常重要)
    1. drop table if exists t_user;
    2. create table t_user(
    3. id int primary key auto_increment, // id字段自动维护一个自增的数字,从1开始,以1递增。
    4. username varchar(255)
    5. );
    6. insert into t_user(username) values('a');
    7. insert into t_user(username) values('b');
    8. insert into t_user(username) values('c');
    9. insert into t_user(username) values('d');
    10. insert into t_user(username) values('e');
    11. insert into t_user(username) values('f');
    12. select * from t_user;

提示:Oracle当中也提供了一个自增机制,叫做:序列(sequence)对象。

25.6 外键约束

  • 关于外键约束的相关术语:

外键约束: foreign key
外键字段:添加有外键约束的字段
外键值:外键字段中的每一个值

  1. 请设计数据库表,用来维护学生和班级的信息?
  2. 第一种方案:一张表存储所有数据
  3. no(pk) name classno classname
  4. -------------------------------------------------------------------------------------------
  5. 1 zs1 101 北京大兴区经济技术开发区亦庄二中高三1
  6. 2 zs2 101 北京大兴区经济技术开发区亦庄二中高三1
  7. 3 zs3 102 北京大兴区经济技术开发区亦庄二中高三2
  8. 4 zs4 102 北京大兴区经济技术开发区亦庄二中高三2
  9. 5 zs5 102 北京大兴区经济技术开发区亦庄二中高三2
  10. 缺点:冗余。【不推荐】
  11. 第二种方案:两张表(班级表和学生表)
  12. t_class 班级表
  13. cno(pk) cname
  14. --------------------------------------------------------
  15. 101 北京大兴区经济技术开发区亦庄二中高三1
  16. 102 北京大兴区经济技术开发区亦庄二中高三2
  17. t_student 学生表
  18. sno(pk) sname classno(该字段添加外键约束fk)
  19. ------------------------------------------------------------
  20. 1 zs1 101
  21. 2 zs2 101
  22. 3 zs3 102
  23. 4 zs4 102
  24. 5 zs5 102
  • t_student中的classno字段引用t_class表中的cno字段,此时t_student表叫做子表,t_class表叫做父表

顺序要求:
删除数据的时候,先删除子表,再删除父表
添加数据的时候,先添加父表,在添加子表
创建表的时候,先创建父表,再创建子表
删除表的时候,先删除子表,在删除父表

  1. drop table if exists t_student;
  2. drop table if exists t_class;
  3. create table t_class(
  4. cno int,
  5. cname varchar(255),
  6. primary key(cno)
  7. );
  8. create table t_student(
  9. sno int,
  10. sname varchar(255),
  11. classno int,
  12. primary key(sno),
  13. foreign key(classno) references t_class(cno)
  14. );
  15. insert into t_class values(101,'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
  16. insert into t_class values(102,'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy');
  17. insert into t_student values(1,'zs1',101);
  18. insert into t_student values(2,'zs2',101);
  19. insert into t_student values(3,'zs3',102);
  20. insert into t_student values(4,'zs4',102);
  21. insert into t_student values(5,'zs5',102);
  22. insert into t_student values(6,'zs6',102);
  23. select * from t_class;
  24. select * from t_student;
  25. insert into t_student values(7,'lisi',103);
  26. ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails
  27. (`bjpowernode`.INT `t_student_ibfk_1` FOREIGN KEY (`classno`)
  28. REFERENCES `t_class` (`cno`))
  • 外键值可以为NULL?外键可以为NULL。
  • 外键字段引用其他表的某个字段的时候,被引用的字段必须是主键吗?被引用的字段不一定是主键,但至少具有unique约束。

26. 存储引擎(整个内容属于了解内容)

26.1 完整的建表语句

  1. CREATE TABLE `t_x` (
  2. `id` int(11) DEFAULT NULL
  3. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  1. - 注意:在MySQL当中,凡是标识符是可以使用飘号括起来的。最好别用,不通用;建表的时候可以指定存储引擎,也可以指定字符集;mysql默认使用的存储引擎是InnoDB方式;默认采用的字符集是UTF8

26.2 什么是存储引擎

  1. - 存储引擎这个名字只有在mysql中存在。(Oracle中有对应的机制,但是不叫做存储引擎。Oracle中没有特殊的名字,就是“表的存储方式”)
  2. - mysql支持很多存储引擎,每一个存储引擎都对应了一种不同的存储方式。
  3. 每一个存储引擎都有自己的优缺点,需要在合适的时机选择合适的存储引擎。<br />

26.3 查看当前mysql支持的存储引擎

  • show engines \G

    1. mysql 5.5.36版本支持的存储引擎有9个:
    1. *************************** 1. row ***************************
    2. Engine: FEDERATED
    3. Support: NO
    4. Comment: Federated MySQL storage engine
    5. Transactions: NULL
    6. XA: NULL
    7. Savepoints: NULL
    8. *************************** 2. row ***************************
    9. Engine: MRG_MYISAM
    10. Support: YES
    11. Comment: Collection of identical MyISAM tables
    12. Transactions: NO
    13. XA: NO
    14. Savepoints: NO
    15. *************************** 3. row ***************************
    16. Engine: MyISAM
    17. Support: YES
    18. Comment: MyISAM storage engine
    19. Transactions: NO
    20. XA: NO
    21. Savepoints: NO
    22. *************************** 4. row ***************************
    23. Engine: BLACKHOLE
    24. Support: YES
    25. Comment: /dev/null storage engine (anything you write to it disappears)
    26. Transactions: NO
    27. XA: NO
    28. Savepoints: NO
    29. *************************** 5. row ***************************
    30. Engine: CSV
    31. Support: YES
    32. Comment: CSV storage engine
    33. Transactions: NO
    34. XA: NO
    35. Savepoints: NO
    36. *************************** 6. row ***************************
    37. Engine: MEMORY
    38. Support: YES
    39. Comment: Hash based, stored in memory, useful for temporary tables
    40. Transactions: NO
    41. XA: NO
    42. Savepoints: NO
    43. *************************** 7. row ***************************
    44. Engine: ARCHIVE
    45. Support: YES
    46. Comment: Archive storage engine
    47. Transactions: NO
    48. XA: NO
    49. Savepoints: NO
    50. *************************** 8. row ***************************
    51. Engine: InnoDB
    52. Support: DEFAULT
    53. Comment: Supports transactions, row-level locking, and foreign keys
    54. Transactions: YES
    55. XA: YES
    56. Savepoints: YES
    57. *************************** 9. row ***************************
    58. Engine: PERFORMANCE_SCHEMA
    59. Support: YES
    60. Comment: Performance Schema
    61. Transactions: NO
    62. XA: NO
    63. Savepoints: NO
    64. 26.4、常见的存储引擎?
    65. Engine: MyISAM
    66. Support: YES
    67. Comment: MyISAM storage engine
    68. Transactions: NO
    69. XA: NO
    70. Savepoints: NO

26.3.1 MyISAM

  1. - MyISAM这种存储引擎不支持事务
  2. - MyISAMmysql最常用的存储引擎,但是这种引擎不是默认的
  3. - MyISAM采用三个文件组织一张表:

xxx.frm(存储格式的文件)
xxx.MYD(存储表中数据的文件)
xxx.MYI(存储表中索引的文件)
优点:
可被压缩,节省存储空间。并且可以转换为只读表,提高检索效率
缺点:
不支持事务

26.3.2 InnoDB

Engine: InnoDB
Support: DEFAULT
Comment: Supports transactions, row-level locking, and foreign keys
Transactions: YES
XA: YES
Savepoints: YES

  1. - 优点:支持事务、行级锁、外键等。这种存储引擎数据的安全得到保障
  2. - 表的结构存储在xxx.frm文件中
  3. - 数据存储在tablespace这样的表空间中(逻辑概念),无法被压缩,无法转换成只读
  4. - 这种InnoDB存储引擎在MySQL数据库崩溃之后提供自动恢复机制
  5. - InnoDB支持级联删除和级联更新

26.3.3 MEMORY

Engine: MEMORY
Support: YES
Comment: Hash based, stored in memory, useful for temporary tables
Transactions: NO
XA: NO
Savepoints: NO

  1. - 缺点:不支持事务。数据容易丢失。因为所有数据和索引都是存储在内存当中的。
  2. - 优点:查询速度最快。
  3. - 以前叫做HEPA引擎。

27. 事务(Transaction)

27.1、什么是事务

一个事务是一个完整的业务逻辑单元,不可再分;比如:银行账户转账,从A账户向B账户转账10000.需要执行两条update语句:
update t_act set balance = balance - 10000 where actno = ‘act-001’;
update t_act set balance = balance + 10000 where actno = ‘act-002’;
以上两条DML语句必须同时成功,或者同时失败,不允许出现一条成功,一条失败;要想保证以上的两条DML语句同时成功或者同时失败,那么就需要使用数据库的“事务机制”

27.2、和事务相关的语句只有:DML语句。(insert delete update)

为什么?因为它们这三个语句都是和数据库表当中的“数据”相关的。事务的存在是为了保证数据的完整性,安全性

27.3、假设所有的业务都能使用1条DML语句搞定,还需要事务机制吗?

不需要事务。但实际情况不是这样的,通常一个“事儿(事务【业务】)”需要多条DML语句共同联合完成

27.4、事务的特性?

事务包括四大特性:ACID
A: 原子性:事务是最小的工作单元,不可再分
C: 一致性:事务必须保证多条DML语句同时成功或者同时失败
I:隔离性:事务A与事务B之间具有隔离
D:持久性:持久性说的是最终数据必须持久化到硬盘文件中,事务才算成功的结束

27.5、关于事务之间的隔离性

  1. - 事务隔离性存在隔离级别,理论上隔离级别包括4个:

第一级别:读未提交(read uncommitted)
对方事务还没有提交,我们当前事务可以读取到对方未提交的数据,读未提交存在脏读(Dirty Read)现象:表示读到了脏的数据

第二级别:读已提交(read committed)
对方事务提交之后的数据我方可以读取到;这种隔离级别解决了: 脏读现象没有了,读已提交存在的问题是:不可重复读

第三级别:可重复读(repeatable read)
这种隔离级别解决了:不可重复读问题。这种隔离级别存在的问题是:读取到的数据是幻象。

第四级别:序列化读/串行化读(serializable)
解决了所有问题;效率低,需要事务排队。

oracle数据库默认的隔离级别是:读已提交 mysql数据库默认的隔离级别是:可重复读

27.6、演示事务

mysql事务默认情况下是自动提交的。(什么是自动提交?只要执行任意一条DML语句则提交一次。)怎么关闭自动提交?start transaction;

  1. * 准备表:
  2. drop table if exists t_user;
  3. create table t_user(
  4. id int primary key auto_increment,
  5. username varchar(255)
  6. );
  7. * 演示:mysql中的事务是支持自动提交的,只要执行一条DML,则提交一次。
  8. mysql> insert into t_user(username) values('zs');
  9. Query OK, 1 row affected (0.03 sec)
  10. mysql> select * from t_user;
  11. +----+----------+
  12. | id | username |
  13. +----+----------+
  14. | 1 | zs |
  15. +----+----------+
  16. 1 row in set (0.00 sec)
  17. mysql> rollback;
  18. Query OK, 0 rows affected (0.00 sec)
  19. mysql> select * from t_user;
  20. +----+----------+
  21. | id | username |
  22. +----+----------+
  23. | 1 | zs |
  24. +----+----------+
  25. 1 row in set (0.00 sec)
  26. * 演示:使用start transaction;关闭自动提交机制。
  27. mysql> start transaction;
  28. Query OK, 0 rows affected (0.00 sec)
  29. mysql> insert into t_user(username) values('lisi');
  30. Query OK, 1 row affected (0.00 sec)
  31. mysql> select * from t_user;
  32. +----+----------+
  33. | id | username |
  34. +----+----------+
  35. | 1 | zs |
  36. | 2 | lisi |
  37. +----+----------+
  38. 2 rows in set (0.00 sec)
  39. mysql> insert into t_user(username) values('wangwu');
  40. Query OK, 1 row affected (0.00 sec)
  41. mysql> select * from t_user;
  42. +----+----------+
  43. | id | username |
  44. +----+----------+
  45. | 1 | zs |
  46. | 2 | lisi |
  47. | 3 | wangwu |
  48. +----+----------+
  49. 3 rows in set (0.00 sec)
  50. mysql> rollback;
  51. Query OK, 0 rows affected (0.02 sec)
  52. mysql> select * from t_user;
  53. +----+----------+
  54. | id | username |
  55. +----+----------+
  56. | 1 | zs |
  57. +----+----------+
  58. 1 row in set (0.00 sec)
  59. --------------------------------------------------------------------
  60. mysql> start transaction;
  61. Query OK, 0 rows affected (0.00 sec)
  62. mysql> insert into t_user(username) values('wangwu');
  63. Query OK, 1 row affected (0.00 sec)
  64. mysql> insert into t_user(username) values('rose');
  65. Query OK, 1 row affected (0.00 sec)
  66. mysql> insert into t_user(username) values('jack');
  67. Query OK, 1 row affected (0.00 sec)
  68. mysql> select * from t_user;
  69. +----+----------+
  70. | id | username |
  71. +----+----------+
  72. | 1 | zs |
  73. | 4 | wangwu |
  74. | 5 | rose |
  75. | 6 | jack |
  76. +----+----------+
  77. 4 rows in set (0.00 sec)
  78. mysql> commit;
  79. Query OK, 0 rows affected (0.04 sec)
  80. mysql> select * from t_user;
  81. +----+----------+
  82. | id | username |
  83. +----+----------+
  84. | 1 | zs |
  85. | 4 | wangwu |
  86. | 5 | rose |
  87. | 6 | jack |
  88. +----+----------+
  89. 4 rows in set (0.00 sec)
  90. mysql> rollback;
  91. Query OK, 0 rows affected (0.00 sec)
  92. mysql> select * from t_user;
  93. +----+----------+
  94. | id | username |
  95. +----+----------+
  96. | 1 | zs |
  97. | 4 | wangwu |
  98. | 5 | rose |
  99. | 6 | jack |
  100. +----+----------+
  101. 4 rows in set (0.00 sec)
  102. * 演示两个事务,假如隔离级别
  103. 演示第1级别:读未提交
  104. set global transaction isolation level read uncommitted;
  105. 演示第2级别:读已提交
  106. set global transaction isolation level read committed;
  107. 演示第3级别:可重复读
  108. set global transaction isolation level repeatable read;


mysql远程登录:mysql -h192.168.151.18 -uroot -p444

28. 索引

28.1、什么是索引?有什么用?

image.png

  1. - 索引就相当于一本书的目录,通过目录可以快速的找到对应的资源。
  2. - 在数据库方面,查询一张表的时候有两种检索方式:

第一种方式:全表扫描
第二种方式:根据索引检索(效率很高)

  1. - 索引为什么可以提高检索效率呢?

其实最根本的原理是缩小了扫描的范围。

索引虽然可以提高检索效率,但是不能随意的添加索引,因为索引也是数据库当中的对象,也需要数据库不断的维护。是有维护成本的。比如,表中的数据经常被修改这样就不适合添加索引,因为数据一旦修改,索引需要重新排序,进行维护。

添加索引是给某一个字段,或者说某些字段添加索引
select ename,sal from emp where ename = ‘SMITH’;
当ename字段上没有添加索引的时候,以上sql语句会进行全表扫描,扫描ename字段中所有的值;当ename字段上添加索引的时候,以上sql语句会根据索引扫描,快速定位

28.2、怎么创建索引对象?怎么删除索引对象?

创建索引对象:
create index 索引名称 on 表名(字段名);

删除索引对象:
drop index 索引名称 on 表名;

28.3、什么时候考虑给字段添加索引?(满足什么条件)

数据量庞大。(根据客户的需求,根据线上的环境)
该字段很少的DML操作。(因为字段进行修改操作,索引也需要维护)
该字段经常出现在where子句中。(经常根据哪个字段查询)

28.4、注意:主键和具有unique约束的字段自动会添加索引

根据主键查询效率较高。尽量根据主键检索。

28.5、查看sql语句的执行计划:

  1. mysql> explain select ename,sal from emp where sal = 5000;
  2. +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  5. | 1 | SIMPLE | emp | ALL | NULL | NULL | NULL | NULL | 14 | Using where |
  6. +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  7. 给薪资sal字段添加索引:
  8. create index emp_sal_index on emp(sal);
  9. mysql> explain select ename,sal from emp where sal = 5000;
  10. +----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+
  11. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  12. +----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+
  13. | 1 | SIMPLE | emp | ref | emp_sal_index | emp_sal_index | 9 | const | 1 | Using where |
  14. +----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+

28.6、索引底层采用的数据结构是:

B+树

28.7、索引的实现原理?

通过B Tree缩小扫描范围,底层索引进行了排序,分区,索引会携带数据在表中的“物理地址”,最终通过索引检索到数据之后,获取到关联的物理地址,通过物理地址定位表中的数据,效率是最高的。
select ename from emp where ename = ‘SMITH’;
通过索引转换为:
select ename from emp where 物理地址 = 0x3;

28.8、索引的分类?

单一索引:给单个字段添加索引
复合索引: 给多个字段联合起来添加1个索引
主键索引:主键上会自动添加索引
唯一索引:有unique约束的字段上会自动添加索引
….

28.9、索引什么时候失效?

select ename from emp where ename like ‘%A%’;
模糊查询的时候,第一个通配符使用的是%,这个时候索引是失效的

29. 视图(view)

29.1、什么是视图?

站在不同的角度去看到数据。(同一张表的数据,通过不同的角度去看待)

29.2、怎么创建视图?怎么删除视图?

create view myview as select empno,ename from emp;
drop view myview;
注意:只有DQL语句才能以视图对象的方式创建出来

29.3、对视图进行增删改查,会影响到原表数据。(通过视图影响原表数据的,不是直接操作的原表)

可以对视图进行CRUD操作

29.4、面向视图操作?

  1. mysql> select * from myview;
  2. +-------+--------+
  3. | empno | ename |
  4. +-------+--------+
  5. | 7369 | SMITH |
  6. | 7499 | ALLEN |
  7. | 7521 | WARD |
  8. | 7566 | JONES |
  9. | 7654 | MARTIN |
  10. | 7698 | BLAKE |
  11. | 7782 | CLARK |
  12. | 7788 | SCOTT |
  13. | 7839 | KING |
  14. | 7844 | TURNER |
  15. | 7876 | ADAMS |
  16. | 7900 | JAMES |
  17. | 7902 | FORD |
  18. | 7934 | MILLER |
  19. +-------+--------+
  20. create table emp_bak as select * from emp;
  21. create view myview1 as select empno,ename,sal from emp_bak;
  22. update myview1 set ename='hehe',sal=1 where empno = 7369; // 通过视图修改原表数据。
  23. delete from myview1 where empno = 7369; // 通过视图删除原表数据。

29.5、视图的作用?

视图可以隐藏表的实现细节。保密级别较高的系统,数据库只对外提供相关的视图,java程序员只对视图对象进行CRUD

30. DBA命令

30.1、将数据库当中的数据导出

在windows的dos命令窗口中执行:(导出整个库)
mysqldump bjpowernode>D:\bjpowernode.sql -uroot -p333
在windows的dos命令窗口中执行:(导出指定数据库当中的指定表)
mysqldump bjpowernode emp>D:\bjpowernode.sql -uroot –p123

30.2、导入数据

  1. create database bjpowernode;
  2. use bjpowernode;
  3. source D:\bjpowernode.sql

31、数据库设计三范式(重点内容,面试经常问)

31.1、什么是设计范式?

设计表的依据,按照这个三范式设计的表不会出现数据冗余

31.2、三范式都是哪些?

第一范式:任何一张表都应该有主键,并且每一个字段原子性不可再分

第二范式:建立在第一范式的基础之上,所有非主键字段完全依赖主键,不能产生部分依赖

  1. 多对多?三张表,关系表两个外键。
  2. t_student学生表
  3. sno(pk) sname
  4. -------------------
  5. 1 张三
  6. 2 李四
  7. 3 王五
  8. t_teacher 讲师表
  9. tno(pk) tname
  10. ---------------------
  11. 1 王老师
  12. 2 张老师
  13. 3 李老师
  14. t_student_teacher_relation 学生讲师关系表
  15. id(pk) sno(fk) tno(fk)
  16. ----------------------------------
  17. 1 1 3
  18. 2 1 1
  19. 3 2 2
  20. 4 2 3
  21. 5 3 1
  22. 6 3 3


第三范式:建立在第二范式的基础之上,所有非主键字段直接依赖主键,不能产生传递依赖

  1. 一对多?两张表,多的表加外键
  2. 班级t_class
  3. cno(pk) cname
  4. --------------------------
  5. 1 班级1
  6. 2 班级2
  7. 学生t_student
  8. sno(pk) sname classno(fk)
  9. ---------------------------------------------
  10. 101 1 1
  11. 102 2 1
  12. 103 3 2
  13. 104 4 2
  14. 105 5 2

提醒:在实际的开发中,以满足客户的需求为主,有的时候会拿冗余换执行速度

31.3、一对一怎么设计?

一对一设计有两种方案:主键共享

  1. t_user_login 用户登录表
  2. id(pk) username password
  3. --------------------------------------
  4. 1 zs 123
  5. 2 ls 456
  6. t_user_detail 用户详细信息表
  7. id(pk+fk) realname tel ....
  8. ------------------------------------------------
  9. 1 张三 1111111111
  10. 2 李四 1111415621

一对一设计有两种方案:外键唯一

  1. t_user_login 用户登录表
  2. id(pk) username password
  3. --------------------------------------
  4. 1 zs 123
  5. 2 ls 456
  6. t_user_detail 用户详细信息表
  7. id(pk) realname tel userid(fk+unique)....
  8. -----------------------------------------------------------
  9. 1 张三 1111111111 2
  10. 2 李四 1111415621 1