MySQL对象之视图

第1章 MySQL视图的介绍

1.1 视图的认识

第一种方法:客户端工具连接mysql实例后进行查看

1

第二种方法:查看某个库下是否有视图

## 查看sys库下有哪些视图
select
	table_schema as "库名",
	table_name as "表名",
	table_type as "表类型"
from
	information_schema.tables
where
	table_schema="sys" and table_type = "view"
;


1.2 视图的简介

视图的数据来自于select语句的结果集(不能有重复的字段名,可给重复的字段名进行别名),它是为了方便数据的查询,而不是为了方便数据的更改。我们创建视图后:

01:在操作系统上看,就是一个表结构文件.frm,没有.ibd文件;当你mysql实例启动后,视图会根据在创建时指定
    的select语句到相关的基表中查询数据,然后将数据保存到视图中,这样就可以直接通过视图查看到相应数据,
    而不需要再写一次查询语句。若基表的数据发生变化了,视图中的数据可能(看视图中的select语句)也会发生变化。

02:在mysql实例中用 show tables from 库名; 查看到的就是一个表名,但我们可通过information_schema.tales来检查
    它是不是视图(table_type等于view就是视图)

视图是为了方便数据的查询,而不是方便数据的更改

01:视图中的数据可不可以改变,这个不一定,得看视图中的select语句是否有使用函数或者连接查询,若有函数或连接查询
    那么是视图中的数据是不可改变的,会直接报错,反之。
02:视图中的数据若更改了,基表中的相关数据也会改变。     <== but我们不这样干。

视图虽然是为了方便数据的查询,但是在程序开发过程中不要使用视图。

01:若程序开发过程了使用了视图,程序里面就可直接调用视图而得到数据,而不需要再写sql语句了。
02:如果一但需求变更,就得改视图,这时就得需要相关部门的人员(运维人员、DBA)的配合,加大了成本;


第2章 MySQL视图的实践

2.1 测试数据准备

测试数据产生的SQL语句

#### 创建lili库,并进入到lili库下面
create database if not exists lili character set utf8 collate utf8_general_ci;
use lili;         
select database();


#### 准备的基本数据
-- 创建department表
create table if not exists department(
    id int unsigned not null comment"部门ID",
    name varchar(20) not null comment"部门名"
)engine=innodb character set utf8 collate utf8_general_ci comment"部门表";

-- 创建employee表
create table if not exists employee(
	id int unsigned primary key auto_increment comment"序列",
	name varchar(20) not null comment"姓名",
	sex enum('male','female') not null default 'male' comment"性别",
	age int unsigned not null comment"年龄",
	dep_id int unsigned not null comment"部门ID"
)engine=innodb character set utf8 collate utf8_general_ci comment"员工表";

-- 往department表中插入数据
insert into department values
   (200,'技术'),(201,'人力资源'),(202,'销售'),(203,'运营');
commit;

-- 往employee表中插入数据
insert into employee(name,sex,age,dep_id) values
   ('王保长','male',18,200),('刘墉','female',48,201),
   ('喜来乐','male',38,201),('李保田','female',28,202),
   ('刘常明','male',18,200),('纪学礼','female',18,204);
commit;

employee表与department表的关联说明

1


2.2 视图的实践一(select结果集来自于单表)

视图中的select语句使用了函数

#### 需求:统计出employee表中总共有多少员工
mysql> select count(*) from employee;
+----------+
| count(*) |
+----------+
|        6 |
+----------+
1 row in set (0.00 sec)


#### 把 统计employee表中有多少员工的需求 放在一个视图中
create view v_employee_count
  as
    select count(*) from employee;    /* select语句中用到了函数哈 */


#### 查看是否存在v_employee_count
mysql> show tables like "v_employee_count";
+-----------------------------------+
| Tables_in_lili (v_employee_count) |
+-----------------------------------+
| v_employee_count                  |   <== 是存在的哈
+-----------------------------------+
1 row in set (0.00 sec)


#### 查看v_employee_count在操作系统上的表现
mysql> system ls -l /data/mysql/3306/data/lili/v_employee_count.*
-rw-r----- 1 mysql mysql 405 9月   2 02:55 /data/mysql/3306/data/lili/v_employee_count.frm
   ^== 结果只有表结构文件.frm


#### 判断v_employee_count是表还是视图
select
	table_schema,
  table_name,
  table_type
from
	information_schema.tables
where
	table_schema="lili" and table_name="v_employee_count"
;

+--------------+------------------+------------+
| table_schema | table_name       | table_type |
+--------------+------------------+------------+
| lili         | v_employee_count | VIEW       | 
+--------------+------------------+------------+
1 row in set (0.00 sec)             ^== table_type字段的值是view表示v_employee_count是视图


#### 查看视图v_employee_count中的数据
mysql> select * from v_employee_count;
+----------+
| count(*) |
+----------+
|        6 |
+----------+
1 row in set (0.00 sec)


#### 查看视图v_employee_count的创建语句
mysql> show create table v_employee_count\G
*************************** 1. row ***************************
                View: v_employee_count
         Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v_employee_count` AS select count(0) AS `count(*)` from `employee`
character_set_client: utf8
collation_connection: utf8_general_ci
1 row in set (0.00 sec)


#### 需求变更:统计employee表中男员工和女员工各多少人
-- 统计employee表中男/女员工各多少人
select
  sex,
  count(sex)
from
  employee
group by
  sex
;

+--------+------------+
| sex    | count(sex) |
+--------+------------+
| male   |          3 |
| female |          3 |
+--------+------------+
2 rows in set (0.00 sec)

-- 更改v_employee_count视图中的select语句
alter view v_employee_count 
as
	select
	  sex,
	  count(sex)
	from
	  employee
	group by
	  sex
	;

-- 查看v_employee_count视图中的数据
mysql> select * from v_employee_count;
+--------+------------+
| sex    | count(sex) |
+--------+------------+
| male   |          3 |
| female |          3 |
+--------+------------+
2 rows in set (0.00 sec)

-- 查看v_employee_count视图的创建语句
mysql> show create view v_employee_count\G
*************************** 1. row ***************************
                View: v_employee_count
         Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v_employee_count` AS select `employee`.`sex` AS `sex`,count(`employee`.`sex`) AS `count(sex)` from `employee` group by `employee`.`sex`
character_set_client: utf8
collation_connection: utf8_general_ci
1 row in set (0.00 sec)


#### 删除employee表中id=6且name="纪学礼"的记录后,再看视图v_employee_count中的数据
-- 删除employee表中id=6且name=“纪学礼”的记录
mysql> select * from employee where id=6 and name="纪学礼";
+----+-----------+--------+-----+--------+
| id | name      | sex    | age | dep_id |
+----+-----------+--------+-----+--------+
|  6 | 纪学礼    | female |  18 |    204 |
+----+-----------+--------+-----+--------+
1 row in set (0.00 sec)

mysql> delete from employee where id=6 and name="纪学礼";
Query OK, 1 row affected (0.00 sec)

mysql> select * from employee where id=6 and name="纪学礼";
Empty set (0.00 sec)

-- 查看v_employee_count视图中的数据
mysql> select * from v_employee_count;
+--------+------------+
| sex    | count(sex) |
+--------+------------+
| male   |          3 |
| female |          2 |  <== 性别为女的人数只有2个了,因为前面删除的"纪学礼"是female
+--------+------------+
2 rows in set (0.00 sec)


#### 更改v_employee_count中的数据,看是否成功,基表employee表的数据是否会改变
-- 改变v_employee_count中的数据
mysql> select * from v_employee_count;
+--------+------------+
| sex    | count(sex) |
+--------+------------+
| male   |          3 |
| female |          2 |
+--------+------------+
2 rows in set (0.00 sec)

mysql> delete from v_employee_count where sex="male";
ERROR 1288 (HY000): The target table v_employee_count of the DELETE is not updatable
    ^== 直接报错,说table v_employee_count不可更改,因为它是视图,且视图中的select语句
     中使用了函数count();这样视图中的数据不会改变,其基表中的数据也不会改变

-- 查看v_employee_count视图和它对应的基表employee表中的数据
mysql> select * from v_employee_count;   
+--------+------------+
| sex    | count(sex) |
+--------+------------+
| male   |          3 |
| female |          2 |
+--------+------------+
2 rows in set (0.00 sec)

mysql> select * from employee;
+----+-----------+--------+-----+--------+
| id | name      | sex    | age | dep_id |
+----+-----------+--------+-----+--------+
|  1 | 王保长    | male   |  18 |    200 |
|  2 | 刘墉      | female |  48 |    201 |
|  3 | 喜来乐    | male   |  38 |    201 |
|  4 | 李保田    | female |  28 |    202 |
|  5 | 刘常明    | male   |  18 |    200 |
+----+-----------+--------+-----+--------+
5 rows in set (0.00 sec)


#### 删除视图v_employee_count
mysql> drop view v_employee_count;
Query OK, 0 rows affected (0.00 sec)

mysql> show tables like "v_employee_count";
Empty set (0.00 sec)


#### 总结:
01:基于中的数据改变了,视图中的数据也会改变;
02:视图中的select语句若使用了函数,则视图中的数据是不能修改的,会直接报错,但是
    我们不这样干(视图不是为了方便你更改数据的)。

视图中的select语句未使用了函数

## 需求:查询出employee表中员工的姓名、性别、年龄
mysql> select * from employee;
+----+-----------+--------+-----+--------+
| id | name      | sex    | age | dep_id |
+----+-----------+--------+-----+--------+
|  1 | 王保长    | male   |  18 |    200 |
|  2 | 刘墉      | female |  48 |    201 |
|  3 | 喜来乐    | male   |  38 |    201 |
|  4 | 李保田    | female |  28 |    202 |
|  5 | 刘常明    | male   |  18 |    200 |
+----+-----------+--------+-----+--------+
5 rows in set (0.00 sec)


mysql> select name,sex,age from employee;
+-----------+--------+-----+
| name      | sex    | age |
+-----------+--------+-----+
| 王保长    | male   |  18 |
| 刘墉      | female |  48 |
| 喜来乐    | male   |  38 |
| 李保田    | female |  28 |
| 刘常明    | male   |  18 |
+-----------+--------+-----+
5 rows in set (0.00 sec)


## 将需求放在视图v_employee_1视图中
create view v_employee_1
	as 
		select name,sex,age from employee;  /* select语句是没有使用函数和连接查询的哈 */


## 查看视图v_employee_1中的数据
mysql> select * from v_employee_1;
+-----------+--------+-----+
| name      | sex    | age |
+-----------+--------+-----+
| 王保长    | male   |  18 |
| 刘墉      | female |  48 |
| 喜来乐    | male   |  38 |
| 李保田    | female |  28 |
| 刘常明    | male   |  18 |
+-----------+--------+-----+
5 rows in set (0.00 sec)


## 删除视图v_employee_1中的数据(name=“王保长”),看是否成功,再看基表employee表中的数据
mysql> select * from v_employee_1;   # 查看视图v_employee_1中的数据
+-----------+--------+-----+
| name      | sex    | age |
+-----------+--------+-----+
| 王保长    | male   |  18 |
| 刘墉      | female |  48 |
| 喜来乐    | male   |  38 |
| 李保田    | female |  28 |
| 刘常明    | male   |  18 |
+-----------+--------+-----+
5 rows in set (0.00 sec)

mysql> delete from v_employee_1 where name="王保长";  # 删除视图v_employee_1中的数据
Query OK, 1 row affected (0.00 sec)

mysql> select * from v_employee_1;                    # 查看视图v_employee_1中的数据
+-----------+--------+-----+
| name      | sex    | age |
+-----------+--------+-----+
| 刘墉      | female |  48 |
| 喜来乐    | male   |  38 |
| 李保田    | female |  28 |
| 刘常明    | male   |  18 |
+-----------+--------+-----+
4 rows in set (0.00 sec)   <== 可以看出视图v_employee_1中name=“王保长”的记录也不存在


mysql> select * from employee;  # 查看基表employee表中的数据
+----+-----------+--------+-----+--------+
| id | name      | sex    | age | dep_id |
+----+-----------+--------+-----+--------+
|  2 | 刘墉      | female |  48 |    201 |
|  3 | 喜来乐    | male   |  38 |    201 |
|  4 | 李保田    | female |  28 |    202 |
|  5 | 刘常明    | male   |  18 |    200 |
+----+-----------+--------+-----+--------+
4 rows in set (0.00 sec) <== 可以看出基表employee中name=“王保长”的记录也不存在了


## 删除视图v_employee_1
mysql> drop view v_employee_1;
Query OK, 0 rows affected (0.00 sec)

mysql> show tables like "v_employee_1";
Empty set (0.00 sec)

## 总结
01:视图中的select语句没用到函数,视图中的数据是可改变的,同时它的基表中的数据也会改变。
02:but我们不这样干,因为视图是为了方便查询,而不是为了方便数据更改。


2.3 视图的实践二(select结果集来自于多表)

## 需求:统计出技术部的员工信息(姓名、性别、年龄、部门名)
select
	employee.name,
  employee.sex,
  employee.age,
  department.name
from
	employee inner join department
on
  employee.dep_id=department.id
where
  department.name="技术"
;

+-----------+------+-----+--------+
| name      | sex  | age | name   |
+-----------+------+-----+--------+
| 刘常明    | male |  18 | 技术   |
+-----------+------+-----+--------+
1 row in set (0.00 sec)


## 将需求的结果放在视图v_employee2department_1中
create view v_employee2department_1
  as 
	select
		employee.name,
	  employee.sex,
	  employee.age,
	  department.name
	from
		employee inner join department
	on
	  employee.dep_id=department.id
	where
	  department.name="技术"
	;    /* select语句中用到了连接(内连接inner join)查询 */

   PS:会报错错:ERROR 1060 (42S21): Duplicate column name 'name'

create view v_employee2department_1
  as 
	select
		employee.name,
	  employee.sex,
	  employee.age,
	  department.name as "d_name"    /*这里取了个别名 */
	from
		employee inner join department
	on
	  employee.dep_id=department.id
	where
	  department.name="技术"
	; /* select语句中用到了连接(内连接inner join)查询 */

   PS:解决了上面报错


## 查看视图v_employee2department_1中的数据
mysql> show tables like "v_employee2department_1";
+------------------------------------------+
| Tables_in_lili (v_employee2department_1) |
+------------------------------------------+
| v_employee2department_1                  |
+------------------------------------------+
1 row in set (0.00 sec)

mysql> select * from v_employee2department_1;
+-----------+------+-----+--------+
| name      | sex  | age | d_name |
+-----------+------+-----+--------+
| 刘常明    | male |  18 | 技术   |
+-----------+------+-----+--------+
1 row in set (0.00 sec)


## 删除v_employee2department_1视图中的数据(name="刘常明")
mysql> select * from v_employee2department_1;   # 查看视图中的数据
+-----------+------+-----+--------+
| name      | sex  | age | d_name |
+-----------+------+-----+--------+
| 刘常明    | male |  18 | 技术   |
+-----------+------+-----+--------+
1 row in set (0.00 sec)

mysql> delete from v_employee2department_1 where name="刘常明";  # 删除视图中的数据
ERROR 1395 (HY000): Can not delete from join view 'lili.v_employee2department_1'
   ^== 报错:无法从联接视图“lili.v_employee2department_1”中删除

mysql> select * from v_employee2department_1;       # 视图中的数据还是存在的
+-----------+------+-----+--------+
| name      | sex  | age | d_name |
+-----------+------+-----+--------+
| 刘常明    | male |  18 | 技术   |
+-----------+------+-----+--------+
1 row in set (0.00 sec)

mysql> select * from employee where name="刘常明";  # 基表中的数据也是存在的
+----+-----------+------+-----+--------+
| id | name      | sex  | age | dep_id |
+----+-----------+------+-----+--------+
|  5 | 刘常明    | male |  18 |    200 |
+----+-----------+------+-----+--------+
1 row in set (0.00 sec)

## 删除视图v_employee2department_1
mysql> drop view v_employee2department_1;
Query OK, 0 rows affected (0.01 sec)

mysql> show tables like "v_employee2department_1";
Empty set (0.00 sec)

## 总结
视图中的select语句中若使用了连接查询,那么视图中的数据是不可改变的,若改变会直接报错。
当然我们不这样干,视图是为了方便查询,而不是为了方便数据更改。


2.4 视图的总结

01:视图是来自于select的结果集(字段名不能重复,可对重复的字段名取别名);

02:视图在操作系统上就是一个表结构文件.frm,没有数据文件.idb,当mysql实例启动后,
    视图会根据它关联的select语句去基表找数据;
    
03:视图是为了方便数据的查询,而不是方便数据的更改;        ## 五颗星*****

04:基表中的数据变化了,视图中的数据也会变化,            ## 看"03"说明点

05:视图中的数据是可以改变的,但有条件,且我们不这样干;    ## 看"03"说明点
    A:视图中的关联select语句若有使用函数或者连接查询,修改视图中的数据会直接报错;
    B:视图中的关联select语句若没有使用函数或者连接查询,修改视图中的数据会成功,基表中的数据也会变化;

视图的创建语法

## 通过help create view得到的
CREATE
    [OR REPLACE]                            # 若视图存存,则进行替换
    [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]   # 这个是算法
    [DEFINER = user]                        # 用户:你用哪个用户创建的就是哪个用户
    [SQL SECURITY { DEFINER | INVOKER }]    # SQL安全,默认你的sql_mode
    VIEW view_name [(column_list)]          # 视图名
    AS select_statement                     # 关联select语句
    [WITH [CASCADED | LOCAL] CHECK OPTION]  

## 基本使用的语法
create view   [视图名]  as  [select 语句];

查看视图是否存在

## 第一种方法:查看某个业务库下是否有视图
select
  *
from
  information_schema.tables
where
  table_schema="chenliang" and table_type="view"
;      /* 这里是查看chenliang业务库下是否有视图(view) */


## 第二种方法:查看某个业务库下是否有视图
利用客户端工具(SQLyog、naicat)连接到mysql实例实例,点开相应业务库下的"视图"图标,参考1.1章节


## 第三种方法:例如:查看chenliang库下的test1是不是视图
select
	table_schema as "库名",
	table_name as "表名",
	table_type as "表类型"      /* 结果中:若该字段的值是view,就表示是视图,反之. */
from
	information_schema.tables
where
	table_schema="chenliang" and table_name= "test1"
;

查看视图的创建语句

show create view [视图名]

*查看视图中的数据

select * from 视图名

更改视图中关联的select语句

alter view 视图名   as   新的select语句

删除视图

drop view 视图名
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值