老杜 mySql自学笔记day3

  • Post author:
  • Post category:mysql



目录


一.存储引擎(了解)


1.什么是存储引擎?存储引擎有什么用?


2.怎么给表添加常用的引擎


3.查看Mysql支持哪些引擎(讲的较粗)


4.常见的存储引擎


二.事务(Transaction)很重要的章节******


1.什么是事务


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


3.事务是如何完成多条语句同时成功或失败的


4.怎么提交事务,怎么回滚事务


5.事务的特性


三.索引(index)


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


2.怎么创建索引对象?怎么删除索引对象?


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


5、查看语句是否使用了索引


6.索引失效


7.索引的分类


四.视图


1.什么是视图?


2.怎么创建视图?怎么删除视图?


3.视图的用途


4.面向视图操作


五.DBA命令(数据的导入和导出)


六.数据库设计的三范式


1.什么是设计范式?


2、三范式都是哪些?


3.总结


4.嘱咐


一.存储引擎(了解)

1.什么是存储引擎?存储引擎有什么用?

存储引擎这个名字只有在mysql中存在。(Oracle中有对应的机制,但是不叫做存储引擎。Oracle中没有特殊的名字, 就是“表的存储方式”)

mysql支持很多存储引擎,每一个存储引擎都对应了一种不同的存储方式。 每一个存储引擎都有自己的优缺点,需要在合适的时机选择合适的存储引擎。

2.怎么给表添加常用的引擎

查询创建表时使用的引擎

show create table t_student;

显示表创建时的信息,外加使用到得引擎信息

| t_student | CREATE TABLE `t_student` (
  `sno` int NOT NULL,
  `sname` varchar(255) DEFAULT NULL,
  `classno` int DEFAULT NULL,
  PRIMARY KEY (`sno`),
  KEY `classno` (`classno`),
  CONSTRAINT `t_student_ibfk_1` FOREIGN KEY (`classno`) REFERENCES `t_class` (`cno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 |

可以在创建表的最后边“)”的右边指定所用到得字符集和引擎

ENGINE:指定引擎       CHARSET:指定字符集

默认的引擎是:InnoDB  默认的字符集是:utf8mb3


将字符集更换为自己指定的


 create table t_product(
    id int primary key,
    name varchar(255)
 )engine = InnoDB default charset =gbk;

查询

 show create table t_product;


| t_product | CREATE TABLE `t_product` (
  `id` int NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk |

3.查看Mysql支持哪些引擎(讲的较粗)

命令

show engines \G

支持哪些引擎看数据库的版本

Support: YES代表着支持

查看数据库版本

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.28    |
+-----------+

4.常见的存储引擎


MyISAM引擎

Engine: MyISAM
Support: YES
Comment: MyISAM storage engine
Transactions: NO
XA: NO
Savepoints: NO


MyISAM这种存储引擎不支持事务。

MyISAM是mysql最常用的存储引擎,但是这种引擎不是默认的。


MyISAM采用三个文件组织一张表:


xxx.frm(存储格式的文件)

xxx.MYD(存储表中数据的文件)

xxx.MYI(存储表中索引的文件)

优点:可被压缩,节省存储空间。并且可以转换为只读表,提高检索效率。

缺点:不支持事务。


小知识点:

对于一张表来说,有主键或者有unique约束的字段会自动创建索引


mysql当中自带的数据库mysql下的 columns_priv表格使用的就是这个引擎

mysql> show create table  columns_priv;


InnoDB引擎

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


优点:支持事务、行级锁、外键,mvvc(多版本)等。这种存储引擎数据的安全得到保障。

表的结构存储在xxx.frm文件中

数据存储在tablespace这样的表空间中(逻辑概念),无法被压缩,无法转换成只读。

这种InnoDB存储引擎在MySQL数据库崩溃之后提供自动恢复机制。

InnoDB支持级联删除和级联更新。


最大特点:

支持事务,以保证数据的安全。(下面会将什么是事务)


MEMORY引擎

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

特点:每个表以  .frm 为结尾   表级锁机制

缺点:不支持事务。数据容易丢失。因为所有数据和索引都是存储在内存当中的。

优点:查询速度最快。

以前叫做HEPA引擎。

二.事务(Transaction)很重要的章节******

1.什么是事务

一个事务是一个完整的业务逻辑单元,要不同时成功要不同时失败,不可再分。


比如:银行账户转账,从A账户向B账户转账10000.需要执行两条update语句:


从A账户上减去10000元,从b账户上加入10000元

update t_act set balance = balance - 10000 where actno = 'act-001';
update t_act set balance = balance + 10000 where actno = 'act-002';


以上两条DML语句必须同时成功,或者同时失败,不允许出现一条成功,一条失败。

要想保证以上的两条DML语句同时成功或者同时失败,那么就需要使用数据库的“事务机制”。


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


为什么?

因为它们这三个语句都是和数据库表当中的“数据”相关的。

事务的存在是为了保证数据的完整性,安全性。



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

不需要事务。


但实际情况不是这样的,通常一个“事儿(事务【业务】)”需要多条DML语句共同联合完成。本质上:事务就是保证多个DML同时成功或着同时失败

3.事务是如何完成多条语句同时成功或失败的


InnoDB引擎提供了一组用来记录事务性活动的日志

事务开始了:

insert

update

insert

事务结束了

在事务执行的过程当中每一条DML语句都会记录到日志当中(保存历史记录)

在事务执行的过程当中,我们可以提交事务,也可以回滚事务


提交事务?

清空日志当中的记录,将所有的数据放到表当中,永久存储。

提交事务表示事务结束,并且是一种成功的结束。


回滚事务?

清空日志当中的记录,将事务当中执行的DML命令全部撤回。

表示事务结束,并且是一种失败的结束。

4.怎么提交事务,怎么回滚事务

提交:commit

回滚:rollback

mysql事务默认情况下是自动提交的。


什么是自动提交?

只要执行任意一条DML语句则提交一次。


怎么关闭自动提交?

start transaction;

准备表:

drop table if exists t_user;

create table t_user(
id int primary key auto_increment,
username varchar(255)
);


演示

:mysql中的事务是支持自动提交的,只要执行一条DML,则提交一次。

 mysql> insert into t_user(username) values('zs');

 Query OK, 1 row affected (0.03 sec)

 mysql> select * from t_user;
 +----+----------+
 | id | username |
 +----+----------+
 |  1 | zs       |
 +----+----------+
 1 row in set (0.00 sec)

 mysql> rollback;

 Query OK, 0 rows affected (0.00 sec)

 mysql> select * from t_user;
 +----+----------+
 | id | username |
 +----+----------+
 |  1 | zs       |
 +----+----------+
 1 row in set (0.00 sec)



演示:

使用start transaction;关闭自动提交机制。

 mysql> start transaction;

 Query OK, 0 rows affected (0.00 sec)

 mysql> insert into t_user(username) values('lisi');

 Query OK, 1 row affected (0.00 sec)

 mysql> select * from t_user;
 +----+----------+
 | id | username |
 +----+----------+
 |  1 | zs       |
 |  2 | lisi     |
 +----+----------+
 2 rows in set (0.00 sec)

 mysql> insert into t_user(username) values('wangwu');

 Query OK, 1 row affected (0.00 sec)

 mysql> select * from t_user;
 +----+----------+
 | id | username |
 +----+----------+
 |  1 | zs       |
 |  2 | lisi     |
 |  3 | wangwu   |
 +----+----------+
 3 rows in set (0.00 sec)

 mysql> rollback;
 Query OK, 0 rows affected (0.02 sec)

 mysql> select * from t_user;
 +----+----------+
 | id | username |
 +----+----------+
 |  1 | zs       |
 +----+----------+
 1 row in set (0.00 sec)

从关闭自动提交开始,都是被回滚的DML命令。


案例:

使用start transaction;关闭自动提交机制。在使用commit进行提交

  mysql> start transaction;
  Query OK, 0 rows affected (0.00 sec)

  mysql> insert into t_user(username) values('wangwu');
  Query OK, 1 row affected (0.00 sec)

  mysql> insert into t_user(username) values('rose');
  Query OK, 1 row affected (0.00 sec)

  mysql> insert into t_user(username) values('jack');
  Query OK, 1 row affected (0.00 sec)

  mysql> select * from t_user;
  +----+----------+
  | id | username |
  +----+----------+
  |  1 | zs       |
  |  4 | wangwu   |
  |  5 | rose     |
  |  6 | jack     |
  +----+----------+
  4 rows in set (0.00 sec)

  mysql> commit;
  Query OK, 0 rows affected (0.04 sec)

  mysql> select * from t_user;
  +----+----------+
  | id | username |
  +----+----------+
  |  1 | zs       |
  |  4 | wangwu   |
  |  5 | rose     |
  |  6 | jack     |
  +----+----------+
  4 rows in set (0.00 sec)

  mysql> rollback;
  Query OK, 0 rows affected (0.00 sec)

  mysql> select * from t_user;
  +----+----------+
  | id | username |
  +----+----------+
  |  1 | zs       |
  |  4 | wangwu   |
  |  5 | rose     |
  |  6 | jack     |
  +----+----------+
  4 rows in set (0.00 sec) 

使用commit之后,日志当中的DML命令清空,所以回滚之后没有变化。

演示两个事务,假如隔离级别

演示第1级别:读未提交

set global transaction isolation level read uncommitted;

演示第2级别:读已提交

set global transaction isolation level read committed;

演示第3级别:可重复读

set global transaction isolation level repeatable read;

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


5.事务的特性


事务包括四大特性:ACID



A: 原子性

:事务是最小的工作单元,不可再分。


C: 一致性

:事务必须保证多条DML语句同时成功或者同时失败,保证数据的一致性。


I:隔离性

:事务A与事务B之间具有隔离,类似于多线程并发访问同一张表。


D:持久性

:持久性说的是最终数据必须持久的保存到硬盘文件中。



6.事务之间的隔离性


类比:

事务A和事务B之间的墙可能会很薄也可能会很厚。隔离级别越高,强越厚。

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


第一级别:

读未提交(read uncommitted)

事务A可以读取到事务B还未提交的数据。

读未提交存在脏读(Dirty Read)现象:表示读到了脏的数据。

理论上的级别,显示当中,数据库都是二挡起步的。



第二级别:

读已提交(read committed)

对方事务提交之后的数据我方可以读取到。

这种隔离级别解决了: 脏读现象没有了。

读已提交存在的问题是:每一次读到的数据都不一样,不可重复读,读到的数据都是真实的数据。



第三级别:

可重复读(repeatable read)

这种隔离级别解决了:不可重复读问题。

这种隔离级别存在的问题是:读取到的数据是幻象。


第四级别:

序列化读/串行化读(serializable)

解决了所有问题。

效率低。需要事务排队。

oracle数据库默认的隔离级别是:读已提交。(第二级别)

mysql数据库默认的隔离级别是:可重复读。(第三级别)


第一级:

A事务读到B事务未提交的数据,脏读问题。

第二级:

读到已提交的数据,事务还没有结束,就可以读到DML语句添加的数据了,称为不可重复读取,但读到的数据都是真实的。

第三级:

在事务A执行的时候,不管多久,每次事务A读取到的数据都是一致的,尽管事务B将数据已经给修改了,事务A读到的数据依旧没有变化。读到的都是幻想,数据已将变了,但是事务A看不到。

第四级:

事务排队,一次只处理一个事务,但不能并发,但是解决了所有问题。有些挥刀自宫的味道了。


还有演示但是太多,懒得写了

大致就是打开两个cmd窗口,进行双线操作,模仿并发,分别观看四个隔离级别对于数据查询的影响。

三.索引(index)

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

索引就相当于一本书的目录,通过目录可以快速的找到对应的资源。


对于一本字典来说,查找某个汉字有两种方式:



第一种方式

:一页一页挨着找,直到找到为止,这种查找方式属于全字典扫描。

效率比较低。


第二种方式

:先通过目录(索引)去定位一个大概的位置,然后直接定位到这个

位置,做局域性扫描,缩小扫描的范围,快速的查找。这种查找方式属于通过

索引检索,效率较高。



在数据库方面,查询一张表的时候有两种检索方式:


第一种方式:全表扫描

第二种方式:根据索引检索(效率很高)


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


在实际中,汉语字典前面的目录是排序的,按照a b c d e f….排序,

为什么排序呢?因为只有排序了才会有区间查找这一说!(缩小扫描范围

其实就是扫描某个区间罢了!)其实最根本的原理是缩小了扫描的范围。

在mysql数据库当中索引也是需要排序的,并且这个所以的排序和TreeSet

数据结构相同。TreeSet(TreeMap)底层是一个自平衡的二叉树!在mysql

当中索引是一个B-Tree数据结构。

遵循左小又大原则存放。采用中序遍历方式遍历取数据。


索引的原理图

通过B Tree缩小扫描范围,底层索引进行了排序,分区,索引会携带数据在表中的“物理地址”,

最终通过索引检索到数据之后,获取到关联的物理地址,通过物理地址定位表中的数据,效率

是最高的。

 select ename from emp where ename = 'SMITH';

通过索引转换为:

select ename from emp where 物理地址 = 0x3;


索引的使用限制

索引虽然可以提高检索效率,但是不能随意的添加索引,因为索引也是数据库当中的对象,也需要数据库不断的维护。是有维护成本的。


比如:

表中的数据经常被修改,这样就不适合添加索引,因为数据一旦修改,索引需要重新排序,进行维护

添加索引是给某一个字段,或者说某些字段添加索引。

    select ename,sal from emp where ename = 'SMITH';


当ename字段上没有添加索引的时候,以上sql语句会进行全表扫描,扫描ename字段中所有的值。

当ename字段上添加索引的时候,以上sql语句会根据索引扫描,快速定位。


2.怎么创建索引对象?怎么删除索引对象?


创建索引对象:


create index 索引名称 on 表名(字段名);


删除索引对象:


drop index 索引名称 on 表名;

假设有一张用户表:t_user

id(PK)                    name                        每一行记录在硬盘上都有物理存储编号
----------------------------------------------------------------------------------
100                        zhangsan                    0x1111
120                        lisi                        0x2222
99                         wangwu                      0x8888
88                         zhaoliu                     0x9999
101                        jack                        0x6666
55                         lucy                        0x5555
130                        tom                         0x7777


提醒1

:在任何数据库当中主键上都会自动添加索引对象,id字段上自动有索引,

因为id是PK。另外在mysql当中,一个字段上如果有unique约束的话,也会自动

创建索引对象。


提醒2

:在任何数据库当中,任何一张表的任何一条记录在硬盘存储上都有

一个硬盘的物理存储编号。


提醒3

:在mysql当中,索引是一个单独的对象,不同的存储引擎以不同的形式

存在,在MyISAM存储引擎中,索引存储在一个.MYI文件中。在InnoDB存储引擎中

索引存储在一个逻辑名称叫做tablespace的当中。在MEMORY存储引擎当中索引

被存储在内存当中。

不管索引存储在哪里,索引在mysql当中都是一个树的形式存在。(自平衡二叉树:B-Tree)


创建索引

mysql> create index emp_ename_index on emp(ename);


删除索引

mysql> drop index emp_ename_index on emp;


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


多查询,少修改的情况下使用

数据量庞大。(根据客户的需求,根据线上的环境,提高运行速度)

该字段很少的DML操作。(因为字段进行修改操作,索引也需要维护)

该字段经常出现在where子句中。(经常根据哪个字段查询,提高检索效率)



注意:

主键和具有unique约束的字段自动会添加索引。

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

5、查看语句是否使用了索引

查看语句是否使用了索引

mysql> explain select ename,sal from emp where sal = 5000;
	+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
	| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
	+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
	|  1 | SIMPLE      | emp   | ALL  | NULL          | NULL | NULL    | NULL |   14 | Using where |
	+----+-------------+-------+------+---------------+------+---------+------+------+-------------+

看rows记录,进行了多少次扫描,是不是全表扫描。


给薪资sal字段添加索引:

create index emp_sal_index on emp(sal);

查看搜索的结果:


	
mysql> explain select ename,sal from emp where sal = 5000;
	+----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+
	| id | select_type | table | type | possible_keys | key           | key_len | ref   | rows | Extra       |
	+----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+
	|  1 | SIMPLE      | emp   | ref  | emp_sal_index | emp_sal_index | 9       | const |    1 | Using where |
	+----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+

rows为1,检索效率效果提升显著

6.索引失效

失效的第一种情况:

	select ename from emp where ename like '%A%';

模糊查询的时候,第一个通配符使用的是%,这个时候索引是失效的。

  mysql> explain select * from emp where ename like '%T';
  +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
  +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  |  1 | SIMPLE      | emp   | ALL  | NULL          | NULL | NULL    | NULL |   14 | Using where |
  +----+-------------+-------+------+---------------+------+---------+------+------+-------------+


失效的第2种情况:


使用or的时候会失效,如果使用or那么要求or两边的条件字段都要有

索引,才会走索引,如果其中一边有一个字段没有索引,那么另一个

字段上的索引也会实现。所以这就是为什么不建议使用or的原因。

  mysql> explain select * from emp where ename = 'KING' or job = 'MANAGER';
  +----+-------------+-------+------+-----------------+------+---------+------+------+-------------+
  | id | select_type | table | type | possible_keys   | key  | key_len | ref  | rows | Extra       |
  +----+-------------+-------+------+-----------------+------+---------+------+------+-------------+
  |  1 | SIMPLE      | emp   | ALL  | emp_ename_index | NULL | NULL    | NULL |   14 | Using where |
  +----+-------------+-------+------+-----------------+------+---------+------+------+-------------+



失效的第3种情况:


使用复合索引的时候,没有使用左侧的列查找,索引失效


什么是复合索引?


两个字段,或者更多的字段联合起来添加一个索引,叫做复合索引。

左列job成功使用索引,使用sal查询的话索引失效

  create index emp_job_sal_index on emp(job,sal);
  
  mysql> explain select * from emp where job = 'MANAGER';
  +----+-------------+-------+------+-------------------+-------------------+---------+-------+------+-------------+
  | id | select_type | table | type | possible_keys     | key               | key_len | ref   | rows | Extra       |
  +----+-------------+-------+------+-------------------+-------------------+---------+-------+------+-------------+
  |  1 | SIMPLE      | emp   | ref  | emp_job_sal_index | emp_job_sal_index | 30      | const |    3 | Using where |
  +----+-------------+-------+------+-------------------+-------------------+---------+-------+------+-------------+

  mysql> explain select * from emp where sal = 800;

  +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
  +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  |  1 | SIMPLE      | emp   | ALL  | NULL          | NULL | NULL    | NULL |   14 | Using where |
  +----+-------------+-------+------+---------------+------+---------+------+------+-------------+


失效的第4种情况:


在where当中索引列参加了运算,索引失效。

  mysql> create index emp_sal_index on emp(sal);

  explain select * from emp where sal = 800;
  +----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+
  | id | select_type | table | type | possible_keys | key           | key_len | ref   | rows | Extra       |
  +----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+
  |  1 | SIMPLE      | emp   | ref  | emp_sal_index | emp_sal_index | 9       | const |    1 | Using where |
  +----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+
//失效

  mysql> explain select * from emp where sal+1 = 800;
  +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
  +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  |  1 | SIMPLE      | emp   | ALL  | NULL          | NULL | NULL    | NULL |   14 | Using where |
  +----+-------------+-------+------+---------------+------+---------+------+------+-------------+


失效的第5种情况:


在where当中索引列使用了函数

  explain select * from emp where lower(ename) = 'smith';
  +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
  +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
  |  1 | SIMPLE      | emp   | ALL  | NULL          | NULL | NULL    | NULL |   14 | Using where |
  +----+-------------+-------+------+---------------+------+---------+------+------+-------------+

7.索引的分类

单一索引:一个字段上添加索引。

复合索引:两个字段或者更多的字段上添加索引。

主键索引:主键上添加索引。

唯一性索引:具有unique约束的字段上添加索引。

…..


注意

:唯一性比较弱的字段上添加索引用处不大。

四.视图

1.什么是视图?

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



2.怎么创建视图?怎么删除视图?

创建视图对象:

  create view dept2_view as select * from dept2;

删除视图对象:

  drop view dept2_view;


注意:

只有DQL语句才能以view的形式创建。

create view view_name as 这里的语句必须是DQL语句;

3.视图的用途


方便,简化开发,安全,利于维护


我们可以面向视图对象进行增删改查,对视图对象的增删改查,会导致

原表被操作!(视图的特点:通过对视图的操作,会影响到原表数据。)

//面向视图查询
select * from dept2_view; 

// 面向视图插入
insert into dept2_view(deptno,dname,loc) values(60,'SALES', 'BEIJING');

// 查询原表数据
mysql> select * from dept2;
+--------+------------+----------+
| DEPTNO | DNAME      | LOC      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
|     60 | SALES      | BEIJING  |
+--------+------------+----------+

// 面向视图删除
mysql> delete from dept2_view;

// 查询原表数据
mysql> select * from dept2;
Empty set (0.00 sec)


假设有一条非常复杂的SQL语句,而这条SQL语句需要在不同的位置上反复使用。每一次使用这个sql语句的时候都需要重新编写,很长,很麻烦,怎么办?


可以把这条复杂的SQL语句以视图对象的形式新建。在需要编写这条SQL语句的位置直接使用视图对象,可以大大简化开发。并且利于后期的维护,因为修改的时候也只需要修改一个位置就行,只需要修改视图对象所映射的SQL语句。

我们以后面向视图开发的时候,使用视图的时候可以像使用table一样。

可以对视图进行增删改查等操作。

视图不是在内存当中,视图对象也是存储在硬盘上的,不会消失。

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


再提醒一下:


视图对应的语句只能是DQL语句。

但是视图对象创建完成之后,可以对视图进行增删改查等操作。



4.面向视图操作

	mysql> select * from myview;
	+-------+--------+
	| empno | ename  |
	+-------+--------+
	|  7369 | SMITH  |
	|  7499 | ALLEN  |
	|  7521 | WARD   |
	|  7566 | JONES  |
	|  7654 | MARTIN |
	|  7698 | BLAKE  |
	|  7782 | CLARK  |
	|  7788 | SCOTT  |
	|  7839 | KING   |
	|  7844 | TURNER |
	|  7876 | ADAMS  |
	|  7900 | JAMES  |
	|  7902 | FORD   |
	|  7934 | MILLER |
	+-------+--------+

	create table emp_bak as select * from emp;

	create view myview1 as select empno,ename,sal from emp_bak;

	update myview1 set ename='hehe',sal=1 where empno = 7369; // 通过视图修改原表数据。

	delete from myview1 where empno = 7369; // 通过视图删除原表数据。



五.DBA命令(数据的导入和导出)

重点掌握:

数据的导入和导出(数据的备份)

其它命令了解一下即可。


数据导出?


注意:在windows的dos命令窗口中:

    mysqldump bjpowernode>D:\bjpowernode.sql -uroot -p123456



可以导出指定的表吗?

mysqldump bjpowernode emp>D:\bjpowernode.sql -uroot -p123456


数据导入



注意:

需要先登录到mysql数据库服务器上。

然后创建数据库:create database bjpowernode;

使用数据库:use bjpowernode

然后初始化数据库:source D:\bjpowernode.sql

六.数据库设计的三范式

1.什么是设计范式?

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

2、三范式都是哪些?

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

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

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


声明:

三范式是面试官经常问的,所以一定要熟记在心!

设计数据库表的时候,按照以上的范式进行,可以避免表中数据的冗余,空间的浪费。


第一范式


最核心,最重要的范式,所有表的设计都需要满足。

必须有主键,并且每一个字段都是原子性不可再分。

学生编号   学生姓名        联系方式
------------------------------------------
1001		张三		zs@gmail.com,1359999999
1002		李四		ls@gmail.com,13699999999
1001		王五		ww@163.net,13488888888


以上是学生表,满足第一范式吗?


不满足,第一:没有主键。第二:联系方式可以分为邮箱地址和电话

学生编号(pk)      学生姓名	      邮箱地址	     联系电话
----------------------------------------------------
1001				张三		zs@gmail.com	1359999999
1002				李四		ls@gmail.com	13699999999
1003				王五		ww@163.net		13488888888



第二范式:


建立在第一范式的基础之上,

要求所有非主键字段必须完全依赖主键,不要产生部分依赖。

学生编号       学生姓名   教师编号  教师姓名
----------------------------------------------------
1001			张三		001		王老师
1002			李四		002		赵老师
1003			王五		001		王老师
1001			张三		002		赵老师


这张表描述了学生和老师的关系:(1个学生可能有多个老师,1个老师有多个学生)

这是非常典型的:多对多关系!


分析以上的表是否满足第一范式?


不满足第一范式。


怎么满足第一范式呢?

修改

学生编号+教师编号(pk)		  学生姓名          教师姓名
----------------------------------------------------
1001			001				张三			王老师
1002			002				李四			赵老师
1003			001				王五			王老师
1001			002				张三			赵老师

学生编号 教师编号,两个字段联合做主键,复合主键(PK: 学生编号+教师编号)


经过修改之后,以上的表满足了第一范式。但是满足第二范式吗?


不满足,“张三”依赖1001,“王老师”依赖001,显然产生了部分依赖。


产生部分依赖有什么缺点?


数据冗余了。空间浪费了。“张三”重复了,“王老师”重复了。

为了让以上的表满足第二范式,你需要这样设计:

  学生表
  学生编号(pk)		学生名字
  ------------------------------------
  1001					张三
  1002					李四
  1003					王五
  
  教师表
  教师编号(pk)		教师姓名
  --------------------------------------
  001					王老师
  002					赵老师

  学生教师关系表
  id(pk)			学生编号(fk)			教师编号(fk)
  ------------------------------------------------------
  1						1001						001
  2						1002						002
  3						1003						001
  4						1001						002



多对多怎么设计?


多对多,三张表,关系表两个外键!!!!!!!!!!!!!!!


第三范式


第三范式建立在第二范式的基础之上

要求所有非主键字典必须直接依赖主键,不要产生传递依赖。

学生编号(PK)     学生姓名     班级编号         班级名称
---------------------------------------------------------
  1001                张三        01            一年一班
  1002                李四        02            一年二班
  1003                王五        03            一年三班
  1004                赵六        03            一年三班

以上表的设计是描述:班级和学生的关系。很显然是1对多关系!

一个教室中有多个学生。


分析以上表是否满足第一范式?


满足第一范式,有主键。


分析以上表是否满足第二范式?


满足第二范式,因为主键不是复合主键,没有产生部分依赖。主键是单一主键。


分析以上表是否满足第三范式?


第三范式要求:不要产生传递依赖!

一年一班依赖01,01依赖1001,产生了传递依赖。

不符合第三范式的要求。产生了数据的冗余。


那么应该怎么设计一对多呢?

  班级表:一
  班级编号(pk)                  班级名称
  ----------------------------------------
  01                                一年一班
  02                                一年二班
  03                                一年三班

  学生表:多

  学生编号(PK)    学生姓名    班级编号(fk)
  -------------------------------------------
  1001                张三            01            
  1002                李四            02            
  1003                王五            03            
  1004                赵六            03   



背口诀:


一对多,两张表,多的表加外键!!!!!!!!!!!!



提醒:

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

3.总结


一对多:


一对多,两张表,多的表加外键!!!!!!!!!!!!


多对多:


多对多,三张表,关系表两个外键!!!!!!!!!!!!!!!


一对一:


一对一放到一张表中不就行了吗?为啥还要拆分表?

在实际的开发中,可能存在一张表字段太多,太庞大。这个时候要拆分表。



一对一怎么设计?


没有拆分表之前:一张表

    t_user
    id        login_name        login_pwd        real_name        email                address........
    ---------------------------------------------------------------------------
    1            zhangsan        123                张三                zhangsan@xxx
    2            lisi            123                李四                lisi@xxx
    ...

这种庞大的表建议拆分为两张:


t_login 登录信息表

    id(pk)        login_name        login_pwd    
    ---------------------------------
    1                zhangsan        123            
    2                lisi            123   


t_user 用户详细信息表

    id(pk)        real_name        email                address........    login_id(fk+unique)
    -----------------------------------------------------------------------------------------
    100            张三                zhangsan@xxx                                1
    200            李四                lisi@xxx                                    2


口诀:一对一,外键唯一!!!!!!!!!!

4.嘱咐

数据库设计三范式是理论上的。

实践和理论有的时候有偏差。

最终的目的都是为了满足客户的需求,有的时候会拿冗余换执行速度。

因为在sql当中,表和表之间连接次数越多,效率越低。(笛卡尔积)

有的时候可能会存在冗余,但是为了减少表的连接次数,这样做也是合理的,

并且对于开发人员来说,sql语句的编写难度也会降低。



版权声明:本文为m0_67946241原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。