【MySQL】视图

目录

[0. 什么是视图](#0. 什么是视图)

[1. 创建视图](#1. 创建视图)

[&& 数据准备](#&& 数据准备)

[&& 示例(后续操作会用到示例中视图)](#&& 示例(后续操作会用到示例中视图))

[2. 视图的查询](#2. 视图的查询)

[2.1 查看数据库中的视图](#2.1 查看数据库中的视图)

[2.2 查看创建视图的语句](#2.2 查看创建视图的语句)

[2.3 查看视图结构](#2.3 查看视图结构)

[2.4 查询视图中的内容](#2.4 查询视图中的内容)

[3. 修改数据](#3. 修改数据)

[3.1 修改真实表](#3.1 修改真实表)

[3.2 修改视图](#3.2 修改视图)

[4. 删除视图](#4. 删除视图)

[5. 视图的优点](#5. 视图的优点)


0. 什么是视图

视图(View) 是一个虚拟表 ,它不实际存储数据,而是基于一个或多个底层表(称为基表)的查询结果。你可以把视图看作是一个保存的查询 或者一个预定义的查询模板

视图本⾝并不占用物理存储空间 ,它仅仅是⼀个查询的逻辑表⽰,物理上它依赖于真实表中的数 据。

1. 创建视图

语法:

create view 视图名 [ (视图列表) ] as select语句;

  • as的后面是查询语句,也就是虚拟表。
  • 如果要使用视图列表,那么必须用小括号 括起来,且视图列表中的字段数量和类型必须与select语句中的查询列表一一对应。
  • 视图列表可以直接给查询列表中的字段起别名(重命名)
  • 视图名称一般以 "v_" 开头
  • select语句包括普通查询、子查询和合并查询等。

&& 数据准备

在开始展示视图之前,我们要有下面这样的4张表:

1.班级表

sql 复制代码
 drop table if exists class;
 create table class (
   id bigint primary key auto_increment,
   name varchar(20)
 );

 insert into class(name) values ('Java001班'), ('C++001班'), ('前端001班');
 SELECT * FROM class;

2.学生表

sql 复制代码
drop table if exists student;
 create table student (
 id bigint primary key auto_increment,
 name varchar(20) not null, 
 sno varchar(10) not null,
 age int default 18,
 gender tinyint(1), 
 enroll_date date,
 class_id bigint,
 foreign key (class_id) references class(id)
);

insert into student (name, sno, age, gender, enroll_date, class_id) values  
('唐三藏', '100001', 18, 1, '1986-09-01', 1),  
('孙悟空', '100002', 18, 1, '1986-09-01', 1),  
('猪悟能', '100003', 18, 1, '1986-09-01', 1),  
('沙悟净', '100004', 18, 1, '1986-09-01', 1),  
('宋江', '200001', 18, 1, '2000-09-01', 2),  
('武松', '200002', 18, 1, '2000-09-01', 2),  
('李莲', '200003', 18, 1, '2000-09-01', 2),  
('不想毕业', '200004', 18, 1, '2000-09-01', 2);

SELECT * FROM student;

3.课程表

sql 复制代码
 drop table if exists course;
 create table course (
  id bigint primary key auto_increment,
  name varchar(20)
 );

 insert into course (name) values ('Java'), ('C++'), ('MySQL'), ('操作系统'), ('计算机网络'), ('数据结构');
 SELECT * FROM course;

4.分数表

sql 复制代码
drop table if exists score;
 create table score (
 id bigint primary key auto_increment,
 score float,
 student_id bigint,
 course_id bigint,
 foreign key (student_id) references student(id),
 foreign key (course_id) references course(id)
 );

insert into score (score, student_id, course_id) values  
(70.5, 1, 1), (98.5, 1, 3), (33, 1, 5), (98, 1, 6),  
(60, 2, 1), (59.5, 2, 5),  
(33, 3, 1), (68, 3, 3), (99, 3, 5),  
(67, 4, 1), (23, 4, 3), (56, 4, 5), (72, 4, 6),  
(81, 5, 1), (37, 5, 5),  
(56, 6, 2), (43, 6, 4), (79, 6, 6),  
(80, 7, 2), (92, 7, 6);

SELECT * FROM score;

下面的示例要用到联表查询,建议同学们可以先看一下《联合查询(1) ------ 联表查询》这篇文章的知识点。

&& 示例(后续操作会用到示例中视图)

-- 查询学生的所有信息和考试成绩

第一步:先使用使用真实表进行查询

sql 复制代码
select 
  s.id, s.name, s.sno, s.age, s.gender, s.enroll_date, 
  c.id, c.`name`, 
  co.id, co.`name`, 
  sc.id, sc.score 
from 
  student s, 
  class c, 
  course co, 
  score sc
where s.class_id = c.id
  and sc.student_id = s.id
  and sc.course_id = co.id
order by s.id;

第二步:根据查询语句创建视图

虽然select时已经用++表名区分了重复列++ ,但是在名称维度没有被区分出来,在创建视图时这些列会被数据库认为是重复的,因此必须在视图列表中进行重命名

错误示例:没有给班级id、班级名、课程id、课程名 和 分数id 起别名

sql 复制代码
CREATE VIEW  v_student_score AS
 select 
  s.id, s.name, s.sno, s.age, s.gender, s.enroll_date, 
  c.id ,     
  c.`name`, 
  co.id ,
  co.`name`, 
  sc.id ,  
  sc.score 
from 
  student s, 
  class c, 
  course co, 
  score sc
where s.class_id = c.id
 and sc.student_id = s.id
 and sc.course_id = co.id
 order by s.id;

报错了:(遇到一个错误就会结束运行,而第一个错误是因为没有为班级id起别名导致的,所以没有显示其他的 [duplicate column] 重复列)

a. 在select查询列表中起好别名,创建视图 v_student_score

所有的别名:班级id = class_id、班级名 = class_name、课程id = course_id、课程名 = course_name、分数id = score_id

sql 复制代码
CREATE VIEW  v_student_score AS
 select 
  s.id, s.name, s.sno, s.age, s.gender, s.enroll_date, 
  c.id AS class_id,         
  c.`name` AS class_name, 
  co.id AS course_id,
  co.`name` AS course_name, 
  sc.id AS score_id,  
  sc.score 
from 
  student s, 
  class c, 
  course co, 
  score sc
where s.class_id = c.id
 and sc.student_id = s.id
 and sc.course_id = co.id
 order by s.id;

执行结果:

【注意:v_student_score的select语句中含有order by】

a. 在视图列表直接为字段重命名,创建视图 v_student_score_v1

sql 复制代码
 create view v_student_score_v1 (  # 视图列表
  id, name, sno, age, gender, enroll_date, 
  class_id, class_name,       # 班级id和名称的重命名
  course_id, course_name,     # 课程id和名称的重命名
  score_id, score            # 分数id的重命名
 ) AS
 select s.id, s.name, s.sno, s.age, s.gender, s.enroll_date, c.id, c.`name`, 
  co.id, co.`name`, sc.id, sc.score from student s, class c, course co, score sc
 where s.class_id = c.id
 and sc.student_id = s.id
 and sc.course_id = co.id;

执行结果:

【注意:v_student_score_v1的select语句中没有order by】

2. 视图的查询

2.1 查看数据库中的视图

视图是和表放在一起统一管理的,所以我们可以使用show tables直接查看。

sql 复制代码
 show tables;

注意:没有show views这样的语法。

2.2 查看创建视图的语句

语法:

show create {view | table} 表名;

  • 使用 show create view 或 show create table 都可以查看创建视图的语句,但是不能使用 show create view 来查看创建表的语句。

-- 例1:查看创建v_student_score视图的语句【view关键字】

sql 复制代码
  show create view v_student_score; 

"创建时使用的语句"的完整展示如下:

-- 例2:查看创建v_student_score视图的语句【table关键字】

sql 复制代码
  show create table v_student_score_v1; 

2.3 查看视图结构

使用desc关键字即可查看视图的结构。

语法:

desc 视图名;

  • 真实表中的 not null 约束和 default 约束会被视图保留下来,但是key级约束不会继承过来
  • **key级约束的退化:**主键约束和外键约束都会退化成 not null 约束。

-- 查看v_student_score视图的结构

sql 复制代码
DESC v_student_score; 

2.4 查询视图中的内容

查询视图与查询真实表的语法格式并无二致:

语法:

select 查询列表 from 视图名 [where子句] [group by子句] [having子句] [order by子句] [limit子句];

  • 使用视图查询时,查询列表中的字段不能超出 当初创建视图时的视图列表。所以视图常用于隐藏真实表的关键字段
  • 视图(虚拟表)可以与真实表或其他虚拟表进行联表查询。

-- 例1:查询学生的姓名和总分,(要求隐藏学号和各科成绩)

创建并使用视图查询,只能查到学生姓名和总分,不能再添加查询字段:

sql 复制代码
  create view v_student_total_points as 
   select s.id, s.name, sum(sc.score) total 
   from student s, score sc 
   where s.id = sc.student_id 
   group by s.id order by s.id;
sql 复制代码
  SELECT * FROM v_student_total_points;

-- 例2:视图可以与真实表进行表连接查询

sql 复制代码
 SELECT * FROM v_student_total_points v, student stu where v.id = stu.id;

3. 修改数据

语法:

update 表名 | 视图名 set 修改的内容 where 条件;

  • 修改真实表的数据会影响视图。
  • 修改视图的数据会影响真实表。
  • 创建视图时如果select语句中使用了distinct、order by、group by、having,那么该视图不可被修改
  • 创建视图时如果select语句是子查询、union合并查询,那么该视图也不可被修改

3.1 修改真实表

-- 例1:JAVA的科目id是1,把真实表中唐三藏的JAVA成绩修改为99分。

修改前:70.5分

真实表score:

视图v_student_score:

sql 复制代码
  update score set score = 99 where student_id = 1 and course_id = 1;

修改后:99分

真实表score:

视图v_student_score:

可以看到,修改真实表,两者的数据都被修改了。

3.2 修改视图

-- 例2:使用了order by的视图不可被修改

视图v_student_score在创建时的select语句中包含了order by,我们尝试修改改视图:

sql 复制代码
 update v_student_score set score = 80 where score_id = 3; 

报错:


-- 例3:在视图v_student_score_v1中把唐三藏的JAVA成绩修改为80分

修改前:99分

真实表score:

视图v_student_score_v1:

sql 复制代码
  UPDATE v_student_score_v1 SET score = 80 WHERE id = 1 and course_id = 1;

修改后:80分

真实表score:

视图v_student_score_v1:

可以看到,修改视图,两者的数据都被修改了。

4. 删除视图

语法:

drop view [ if exists ] 视图名;

  • 删除视图必须用drop view,不能使用drop table。
  • 删除视图不会影响真实表的数据。

-- 示例:删除视图v_student_total_points

删除前:有17条记录

sql 复制代码
  drop view if EXISTS v_student_total_points;

删除后:只有16条记录了

5. 视图的优点

  1. 简单性 :视图可以将复杂的查询封装成⼀个简单的查询。例如,针对⼀个复杂的多表连接查询,可以创建⼀个视图,⽤⼾只需查询视图⽽⽆需了解底层的复杂逻辑。
  2. 安全性 :通过视图,可以隐藏表中的敏感数据 。例如,⼀个系统的⽤⼾表中,可以创建⼀个不包含密码列视图 ,普通⽤⼾只能访问这个视图,⽽不能访问原始表
  3. 逻辑数据独立性 :视图提供了⼀种逻辑数据独⽴性,即使底层表结构发⽣变化,只需修改视图定义,⽽⽆需修改依赖视图的应⽤程序。使⽤到应用程序与数据库的解耦。
  4. 重命名列:视图允许⽤⼾重命名列名,以增强数据可读性。

本期分享完毕,感谢大家的支持Thanks♪(・ω・)ノ

相关推荐
一 乐1 小时前
宠物医院预约|宠物医院|基于SprinBoot+vue的宠物医院预约管理系统源码+数据库+文档)
java·前端·数据库·vue.js·后端·springboot
Fuly10241 小时前
langchain基础教程(6)---构建知识库--①向量数据库-chromadb
数据库·langchain
凉凉的知识库1 小时前
在Go中读取MySQL Date类型,一不小心就踩坑
mysql·面试·go
橘子编程1 小时前
仓颉语言:华为新一代编程利器
java·c语言·开发语言·数据库·python·青少年编程
changjiahong1 小时前
项目小结总结
mysql
i***39581 小时前
开放自己本机的mysql允许别人连接
数据库·mysql·adb
n***F8751 小时前
【MySQL】视图
数据库·mysql·oracle
p***93031 小时前
使用Django Rest Framework构建API
数据库·django·sqlite
i***68321 小时前
图文详述:MySQL的下载、安装、配置、使用
android·mysql·adb