MySQL -- 02
聚合函数(aggregation)
- count ---- 计数
# count(*) 查看有几条记录 -- 相对低效 mysql> select count(*) from emp; +----------+ | count(*) | +----------+ | 5 | +----------+ # count(1) 查看有几条记录 -- 高效 mysql> select count(1) from emp; +----------+ | count(1) | +----------+ | 5 | +----------+ # count(comm) 只统计非null的 -- 低效,需要删选是否为null mysql> select count(comm) from emp; +-------------+ | count(comm) | +-------------+ | 4 | +-------------+
- max、min
# 求工资的最大值 mysql> select sal from emp order by sal desc limit 1; +-------+ | sal | +-------+ | 90000 | +-------+ mysql> select max(sal) from emp; +----------+ | max(sal) | +----------+ | 90000 | +----------+ # 求工资的最小值 mysql> select sal from emp order by sal asc limit 1; +------+ | sal | +------+ | 3000 | +------+ mysql> select min(sal) from emp; +----------+ | min(sal) | +----------+ | 3000 | +----------+
- sum ---- 求和
mysql> select sum(sal) from emp; +----------+ | sum(sal) | +----------+ | 114500 | +----------+
- avg ---- 求平均值
mysql> select avg(sal) from emp; +----------+ | avg(sal) | +----------+ | 22900 | +----------+
- 练习题
mysql> select * from emp; +-------+-------+------+------+---------------------+-------+---------+--------+ | empno | ename | job | mgr | hiredate | sal | comm | deptno | +-------+-------+------+------+---------------------+-------+---------+--------+ | 100 | jack | 副总 | NULL | 2002-05-01 00:00:00 | 90000 | NULL | 1 | | 200 | tony | 总监 | 100 | 2015-02-02 00:00:00 | 10000 | 2000.00 | 2 | | 300 | hana | 经理 | 200 | 2017-02-02 00:00:00 | 8000 | 1000.00 | 2 | | 400 | leo | 员工 | 300 | 2019-02-22 00:00:00 | 3000 | 200.12 | 2 | | 500 | liu | 员工 | 300 | 2019-03-19 00:00:00 | 3500 | 200.58 | 2 | +-------+-------+------+------+---------------------+-------+---------+--------+ # 查询工资大于等于8000的人数 mysql> select count(*) from emp where sal>=8000; +----------+ | count(*) | +----------+ | 3 | +----------+ # 查询入职年份为2019的人数 mysql> select count(*) from emp where year(hiredate)=2019; +----------+ | count(*) | +----------+ | 2 | +----------+
分组
- 当查询的结果中即出现了非聚合列又出现了聚合列,就必须分组(通常按照非聚合列分组)
group by
表示分组,having
子句类似where过滤返回的结果- group by ---- 分组
# 查询每个部门中的最高薪资和平均薪资 mysql> select deptno,max(sal),avg(sal) from emp group by deptno; +--------+----------+----------+ | deptno | max(sal) | avg(sal) | +--------+----------+----------+ | 1 | 90000 | 90000 | | 2 | 10000 | 6125 | +--------+----------+----------+ # 查询每个岗位的最高薪资和平均薪资 mysql> select job,max(sal),avg(sal) from emp group by job; +------+----------+----------+ | job | max(sal) | avg(sal) | +------+----------+----------+ | 副总 | 90000 | 90000 | | 总监 | 10000 | 10000 | | 经理 | 8000 | 8000 | | 员工 | 3500 | 3250 | +------+----------+----------+ # 统计每年的入职人数 mysql> select year(hiredate),count(*) from emp group by year(hiredate); +----------------+----------+ | year(hiredate) | count(*) | +----------------+----------+ | 2002 | 1 | | 2015 | 1 | | 2017 | 1 | | 2019 | 2 | +----------------+----------+
- having ---- 用来对分组后的数据,进一步过滤
# 统计每个部门的平均薪资,只要>10000的记录 mysql> select deptno,avg(sal) from emp group by deptno having avg(sal)>10000; +--------+----------+ | deptno | avg(sal) | +--------+----------+ | 1 | 90000 | +--------+----------+ # 统计每个岗位的最高薪资,只要>8000的数据,并按薪资排序(升序) mysql> select job,max(sal) from emp group by job having max(sal)>8000 order by max(sal); +------+----------+ | job | max(sal) | +------+----------+ | 总监 | 10000 | | 副总 | 90000 | +------+----------+ # 统计每年的入职人数,只要人数>1的记录 mysql> select year(hiredate),count(*) from emp group by year(hiredate) having count(*)>1; +----------------+----------+ | year(hiredate) | count(*) | +----------------+----------+ | 2019 | 2 | +----------------+----------+ # 统计每年的入职人数,只要2017年以后的记录
事务 (transaction)
1. 概述
- 数据库事务(Database Transaction),是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
- 简单的说:事务就是将一堆的SQL语句(通常是增删改操作)绑定在一起执行,要么都执行成功,要么都执行失败,即都执行成功才算成功,否则就会恢复到这堆SQL执行之前的状态。
2. 四个特性(ACID)
- 一般来说,事务是必须满足4个条件(ACID):原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。
# 使用 start transaction开启事务,commit 提交事务 # 没有使用commit提交之前,数据库中其实没有真正插入数据,只在本窗口有效,重开一个窗口或者关闭本窗口重开,都无法查询到刚才的数据 # 若不提交,或者使用rollback回滚,则数据库中没有信息 mysql> start transaction; mysql> insert into dept values(10,'java','北京'); mysql> insert into dept values(11,'java2','北京2'); mysql> commit;
- 原子性(Atomicity):
- 一个事务(transaction)中的所有操作,要么全部执行成功,要么全部执行失败,不会结束在中间某个环节。
- 事务在执行过程中如果发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
- 一致性(Consistency):
- 事务必须使数据库从一个一致性状态变换到另外一个一致性状态。在事务开始之前和事务结束以后,数据库的完整性没有被破坏。
- 这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
- 比如:张三和李四共有1000元,无论两者之间发生多少次转账,总和都应该是1000,不会出现张三给李四转了500,李四的账户却没有增加500的情况。
- 隔离性(Isolation):
- 事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
- 数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。
- 持久性(Durability):持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
- 原子性(Atomicity):
3. 隔离级别
- 1、事务具有ACID特性
- 原子性(atomicity):一个事务被事务不可分割的最小工作单元,要么全部提交,要么全部失败回滚。
- 一致性(consistency):数据库总是从一致性状态到另一个一致性状态,它只包含成功事务提交的结果
- 隔离型(isolation):事务所做的修改在最终提交一起,对其他事务是不可见的
- 持久性(durability):一旦事务提交,则其所做的修改就会永久保存到数据库中。
- 2、事务的隔离级别
- 1)隔离级别的定义与问题
- READ UNCOMMITTED(读未提交):事务的修改,即使没有提交,对其他事务也都是可见的。事务能够读取未提交的数据,这种情况称为脏读。
- READ COMMITTED(读已提交):事务读取已提交的数据,大多数数据库的默认隔离级别。当一个事务在执行过程中,数据被另外一个事务修改,造成本次事务前后读取的信息不一样,这种情况称为不可重复读。
- PEPEATABLE READ(可重复读):这个级别是MySQL的默认隔离级别,它解决了脏读的问题,同时也保证了同一个事务多次读取同样的记录是一致的,但这个级别还是会出现幻读的情况。幻读是指当一个事务A读取某一个范围的数据时,另一个事务B在这个范围插入行,A事务再次读取这个范围的数据时,会产生幻行。特别说明:InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决了幻读问题,它使用间隙锁(next-key locking)锁定查询涉及的行和索引中的间隙,防止幻影行的插入。
- SERIALIZABLE(可串行化):这个事务是最高的隔离级别,它强制事务串行执行,避免了幻读问题。简单来说,SERIALIZABLE会在读取的每一行数据上都加锁,所以可能会导致大量的超时和锁竞争
隔离级别 脏读可能性 不可重复度可能性 幻读可能性 加锁读 READ UNCONMITED(读未提交) √ √ √ × RED COMMITED(读已提交) × √ √ × REPEATABLE READ(可重复读) × × √ × SERIALIZABLE(可串行化) × × × √
- 1)隔离级别的定义与问题
约束
4. 约束
- 主键约束 primary key
- 唯一约束 unique
- 非空约束 not null
- 默认约束 default
- 检查约束 check
# default 表示默认值,若不给该列赋值,会添加默认值 # check 会检查对应列所输入的数据是否合格 create table tb_user( id int primary key auto_increment, name varchar(10) unique not null, sex varchar(10) default '男', age int not null, check(age>0 and age<100) );
- 外键约束 foreign key ----
foreign key(本表的主键) references 关联表(主键)
# foreign key(本表的主键) references 关联表(主键) # 子表添加记录时,id必须取自主表 # 删除主表记录时,必须没有被子表使用着 create table tb_user_address( user_id int primary key auto_increment, address varchar(20), foreign key(user_id) references tb_user(id) );
索引
5. 索引
- 概述
- 分类
- 单值索引:一个索引只包括一个列,一个表可以有多个列
- 唯一索引:索引列的值必须唯一,但允许有空值;主键会自动创建唯一索引
- 复合索引:一个索引同时包括多列
- 使用
- 查看索引,主键列会自动创建索引
mysql> show index from dept; +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | dept | 0 | PRIMARY | 1 | deptno | A | 8 | NULL | NULL | | BTREE | | | YES | NULL | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
- 创建索引(单值索引)
# 创建索引 # create index 索引名字 on 表名(字段名); # 一般索引名字可以命名为 字段名_index mysql> create index job_index on emp(job); Query OK, 0 rows affected (0.06 sec) Records: 0 Duplicates: 0 Warnings: 0 # 查看索引 mysql> show index from emp; +-------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression | +-------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | emp | 0 | PRIMARY | 1 | empno | A | 5 | NULL | NULL | | BTREE | | | YES | NULL | | emp | 1 | job_index | 1 | job | A | 4 | NULL | NULL | YES | BTREE | | | YES | NULL | +-------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
- 查看数据
# 语法上和未加索引一致,只是查询列为job,已加索引则更加高效 # 背后会用 job 的索引 mysql> select * from emp where job='经理'; +-------+-------+------+------+---------------------+------+---------+--------+ | empno | ename | job | mgr | hiredate | sal | comm | deptno | +-------+-------+------+------+---------------------+------+---------+--------+ | 300 | hana | 经理 | 200 | 2017-02-02 00:00:00 | 8000 | 1000.00 | 2 | +-------+-------+------+------+---------------------+------+---------+--------+
- 创建唯一索引
# 创建唯一索引 # 索引列的值必须唯一 mysql> alter table emp add unique(ename); Query OK, 0 rows affected (0.06 sec) Records: 0 Duplicates: 0 Warnings: 0 # 使用唯一索引 mysql> select * from emp where ename='jack'; +-------+-------+------+------+---------------------+-------+------+--------+ | empno | ename | job | mgr | hiredate | sal | comm | deptno | +-------+-------+------+------+---------------------+-------+------+--------+ | 100 | jack | 副总 | NULL | 2002-05-01 00:00:00 | 90000 | NULL | 1 | +-------+-------+------+------+---------------------+-------+------+--------+
- 创建复合索引
# 创建复合索引 # 注意遵循最左原则,即最左边的列必须有效,否则索引会失效 mysql> alter table emp add index many_index(ename,job,hiredate); Query OK, 0 rows affected (0.05 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show index from emp; +-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression | +-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ | emp | 0 | PRIMARY | 1 | empno | A | 5 | NULL | NULL | | BTREE | | | YES | NULL | | emp | 0 | ename | 1 | ename | A | 5 | NULL | NULL | YES | BTREE | | | YES | NULL | | emp | 1 | job_index | 1 | job | A | 4 | NULL | NULL | YES | BTREE | | | YES | NULL | | emp | 1 | many_index | 1 | ename | A | 5 | NULL | NULL | YES | BTREE | | | YES | NULL | | emp | 1 | many_index | 2 | job | A | 5 | NULL | NULL | YES | BTREE | | | YES | NULL | | emp | 1 | many_index | 3 | hiredate | A | 5 | NULL | NULL | YES | BTREE | | | YES | NULL | +-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+ 6 rows in set (0.02 sec) # 使用复合索引 mysql> select * from emp where ename='jack' and job='副总'; +-------+-------+------+------+---------------------+-------+------+--------+ | empno | ename | job | mgr | hiredate | sal | comm | deptno | +-------+-------+------+------+---------------------+-------+------+--------+ | 100 | jack | 副总 | NULL | 2002-05-01 00:00:00 | 90000 | NULL | 1 | +-------+-------+------+------+---------------------+-------+------+--------+
- 删除索引
alter table emp drop index job_index;
- 分析SQL性能、分析SQL执行计划(查看是否使用索引)
mysql> explain -> select * from emp where job='经理'; +----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-------+ | 1 | SIMPLE | emp | NULL | ref | job_index | job_index | 33 | const | 1 | 100.00 | NULL | +----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-------+
- 查看索引,主键列会自动创建索引
- 使用索引的优缺点
- 优点:
- 创建唯一索引,保证数据库表中每一行数据的唯一性
- 大大加速数据的检索速度,这也是创建索引的最主要的原因
- 加速表和表之间的连接,特别是在实现数据的参考完整性特别有意义
- 使用分组和排序子句进行数据检索时,同样可以减少查询中分组和排序的时间
- 通过使用索引,可以在查询的过程中使用优化隐藏器,提高系统的性能
- 缺点:
- 创建索引和维护索引需要耗费时间,这种时间随着数据量增加而增加
- 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚集引用,那么需要的空间就会更大
- 当对表中的数据进行新增修改删除时,索引也要动态地维护,降低了数据的维护速度
- 优点:
表与表的关系
6. 表与表之间的关系
- 一对一:一一对应关系,比如一个人和他的身份证号
- 一对多:比如部门和员工,一个部门可以有多个员工,一个员工只能属于一个部门
- 多对一:与一对多关系类似
- 多对多:比如学生和老师,一个学生可以有多个老师,一个老师也可以教多个学生
连接查询 (join)
7. 连接查询
- 笛卡尔积(直积)
select * from emp,dept;
笛卡尔积的符号化为: A×B={(x,y)|x∈A∧y∈B} 例如,A={a,b}, B={0,1,2},则 A×B={(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)} B×A={(0, a), (0, b), (1, a), (1, b), (2, a), (2, b)}
- 连接查询
- 内连接 inner join
- 连接查询中,哪个表写在前面,查询出来的结果中,哪个表就出现在左边
- 内连接查询到的是,两张表中都满足条件的数据(取交集)
mysql> select * from dept inner join emp on dept.deptno=emp.deptno; +--------+------------+------+-------+-------+------+------+---------------------+-------+---------+--------+ | deptno | dname | loc | empno | ename | job | mgr | hiredate | sal | comm | deptno | +--------+------------+------+-------+-------+------+------+---------------------+-------+---------+--------+ | 1 | accounting | 一区 | 100 | jack | 副总 | NULL | 2002-05-01 00:00:00 | 90000 | NULL | 1 | | 2 | research | 二区 | 200 | tony | 总监 | 100 | 2015-02-02 00:00:00 | 10000 | 2000.00 | 2 | | 2 | research | 二区 | 300 | hana | 经理 | 200 | 2017-02-02 00:00:00 | 8000 | 1000.00 | 2 | | 2 | research | 二区 | 400 | leo | 员工 | 300 | 2019-02-22 00:00:00 | 3000 | 200.12 | 2 | | 2 | research | 二区 | 500 | liu | 员工 | 300 | 2019-03-19 00:00:00 | 3500 | 200.58 | 2 | +--------+------------+------+-------+-------+------+------+---------------------+-------+---------+--------+ 5 rows in set (0.00 sec) mysql> select * from emp join dept on dept.deptno=emp.deptno; +-------+-------+------+------+---------------------+-------+---------+--------+--------+------------+------+ | empno | ename | job | mgr | hiredate | sal | comm | deptno | deptno | dname | loc | +-------+-------+------+------+---------------------+-------+---------+--------+--------+------------+------+ | 100 | jack | 副总 | NULL | 2002-05-01 00:00:00 | 90000 | NULL | 1 | 1 | accounting | 一区 | | 200 | tony | 总监 | 100 | 2015-02-02 00:00:00 | 10000 | 2000.00 | 2 | 2 | research | 二区 | | 300 | hana | 经理 | 200 | 2017-02-02 00:00:00 | 8000 | 1000.00 | 2 | 2 | research | 二区 | | 400 | leo | 员工 | 300 | 2019-02-22 00:00:00 | 3000 | 200.12 | 2 | 2 | research | 二区 | | 500 | liu | 员工 | 300 | 2019-03-19 00:00:00 | 3500 | 200.58 | 2 | 2 | research | 二区 | +-------+-------+------+------+---------------------+-------+---------+--------+--------+------------+------+ 5 rows in set (0.00 sec) mysql> select * from emp inner join dept on dept.deptno=emp.deptno where empno=100; +-------+-------+------+------+---------------------+-------+------+--------+--------+------------+------+ | empno | ename | job | mgr | hiredate | sal | comm | deptno | deptno | dname | loc | +-------+-------+------+------+---------------------+-------+------+--------+--------+------------+------+ | 100 | jack | 副总 | NULL | 2002-05-01 00:00:00 | 90000 | NULL | 1 | 1 | accounting | 一区 | +-------+-------+------+------+---------------------+-------+------+--------+--------+------------+------+ 1 row in set (0.00 sec)
- 左外连接 left join
- 查询出左边表的所有记录,右边没有数据的用null填充
- 常用,小表驱动大表,小表 left join 大表(左边写数据少的)
mysql> select * from dept left join emp on dept.deptno=emp.deptno; +--------+------------+------+-------+-------+------+------+---------------------+-------+---------+--------+ | deptno | dname | loc | empno | ename | job | mgr | hiredate | sal | comm | deptno | +--------+------------+------+-------+-------+------+------+---------------------+-------+---------+--------+ | 1 | accounting | 一区 | 100 | jack | 副总 | NULL | 2002-05-01 00:00:00 | 90000 | NULL | 1 | | 2 | research | 二区 | 200 | tony | 总监 | 100 | 2015-02-02 00:00:00 | 10000 | 2000.00 | 2 | | 2 | research | 二区 | 300 | hana | 经理 | 200 | 2017-02-02 00:00:00 | 8000 | 1000.00 | 2 | | 2 | research | 二区 | 400 | leo | 员工 | 300 | 2019-02-22 00:00:00 | 3000 | 200.12 | 2 | | 2 | research | 二区 | 500 | liu | 员工 | 300 | 2019-03-19 00:00:00 | 3500 | 200.58 | 2 | | 3 | operations | 二区 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | +--------+------------+------+-------+-------+------+------+---------------------+-------+---------+--------+ 6 rows in set (0.00 sec)
- 右外连接 right join
- 与左外连接相似
- 查询出右边表的所有记录,左边没有数据的用null填充
mysql> select * from emp right join dept on dept.deptno=emp.deptno; +-------+-------+------+------+---------------------+-------+---------+--------+--------+------------+------+ | empno | ename | job | mgr | hiredate | sal | comm | deptno | deptno | dname | loc | +-------+-------+------+------+---------------------+-------+---------+--------+--------+------------+------+ | 100 | jack | 副总 | NULL | 2002-05-01 00:00:00 | 90000 | NULL | 1 | 1 | accounting | 一区 | | 200 | tony | 总监 | 100 | 2015-02-02 00:00:00 | 10000 | 2000.00 | 2 | 2 | research | 二区 | | 300 | hana | 经理 | 200 | 2017-02-02 00:00:00 | 8000 | 1000.00 | 2 | 2 | research | 二区 | | 400 | leo | 员工 | 300 | 2019-02-22 00:00:00 | 3000 | 200.12 | 2 | 2 | research | 二区 | | 500 | liu | 员工 | 300 | 2019-03-19 00:00:00 | 3500 | 200.58 | 2 | 2 | research | 二区 | | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | 3 | operations | 二区 | +-------+-------+------+------+---------------------+-------+---------+--------+--------+------------+------+ mysql> select * from dept right join emp on dept.deptno=emp.deptno; +--------+------------+------+-------+-------+------+------+---------------------+-------+---------+--------+ | deptno | dname | loc | empno | ename | job | mgr | hiredate | sal | comm | deptno | +--------+------------+------+-------+-------+------+------+---------------------+-------+---------+--------+ | 1 | accounting | 一区 | 100 | jack | 副总 | NULL | 2002-05-01 00:00:00 | 90000 | NULL | 1 | | 2 | research | 二区 | 200 | tony | 总监 | 100 | 2015-02-02 00:00:00 | 10000 | 2000.00 | 2 | | 2 | research | 二区 | 300 | hana | 经理 | 200 | 2017-02-02 00:00:00 | 8000 | 1000.00 | 2 | | 2 | research | 二区 | 400 | leo | 员工 | 300 | 2019-02-22 00:00:00 | 3000 | 200.12 | 2 | | 2 | research | 二区 | 500 | liu | 员工 | 300 | 2019-03-19 00:00:00 | 3500 | 200.58 | 2 | +--------+------------+------+-------+-------+------+------+---------------------+-------+---------+--------+
- 内连接 inner join
- 区别:
视图
8. 概述
- 视图是指计算机数据库中的视图,是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。但是,视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。
- 视图是存储在数据库中的查询的SQL 语句,它主要出于两种原因:安全原因, 视图可以隐藏一些数据,如:社会保险基金表,可以用视图只显示姓名,地址,而不显示社会保险号和工资数等,另一原因是可使复杂的查询易于理解和使用。
9. 创建视图,使用视图
- 视图是一张特殊的表,一般将经常需要查询的内容作为一个视图,
- 视图会将其进行缓存,后续的查询只需要查询视图即可
mysql> create view emp_view as (select * from emp where ename like '%a%'); Query OK, 0 rows affected (0.04 sec) mysql> select * from emp_view; +-------+-------+------+------+---------------------+-------+---------+--------+ | empno | ename | job | mgr | hiredate | sal | comm | deptno | +-------+-------+------+------+---------------------+-------+---------+--------+ | 100 | jack | 副总 | NULL | 2002-05-01 00:00:00 | 90000 | NULL | 1 | | 300 | hana | 经理 | 200 | 2017-02-02 00:00:00 | 8000 | 1000.00 | 2 | +-------+-------+------+------+---------------------+-------+---------+--------+ 2 rows in set (0.01 sec)
10. 视图的优缺点
- 优点:
- 简单性:可以快速访问两表或者多表连接查询所组成的数据。对于那些经常被查询的数据,可以定义为视图,从而简化操作,提高效率。
- 安全性:通过视图,用户只能查询和修改他们所能见到的数据。对于某些不想让用户看到的数据可以通过视图筛选和隐藏掉。通过视图,用户可以被限制在数据的不同子集上。
- 逻辑数据的独立性:视图可以使应用程序和数据库表在一定程度上独立。通过视图,可以使程序与数据库表被视图分割开来。
- 缺点:
- 性能:将基本表的查询结果保存为一个视图,需要消耗时间和空间,在资源的使用上会有消耗
- 修改限制:定义为视图后,当用户试图修改部分内容时,数据库必须把它转换为对于基本表的某些信息的修改,这对于简单视图来说可以是很方便的,但是对于复杂视图来说,可能是不可修改的