Mysql学习笔记—视图
1.什么是视图
视图(View)是一种虚拟存在的表。其内容与真实的表相似,包含一系列带有名称的列和行数据。但是视图并不在数据库中以存储的数据的形式存在。行和列的数据来自定义视图时查询所引用的基本表,并且在具体引用视图时动态生成。
通俗的讲,视图就是一条SELECT语句执行后返回的结果集。所以我们在创建视图的时候,主要的工作就落在创建这条SQL查询语句上。
2.视图的作用
- 简单:使用视图的用户完全不需要关心视图中的数据是通过什么查询得到的,视图中的数据对用户来说已经是过滤好的符合条件的结果集;
- 安全:使用视图的用户只能访问他们被允许查询的结果集,对表的权限管理并不能限制到某个行或某个列,但是通过视图就可以简答地实现;
- 数据独立:一旦视图的结构确定了,可以屏蔽表结构变化对用户的影响,原表增加列对视图没有影响;源表修改列名,则可以通过修改视图来解决,不会造成对访问者的影响。
3.视图操作
创建视图
CREATE
[OR REPLACE]
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = { user | CURRENT_USER }]
[SQL SECURITY { DEFINER | INVOKER }]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
ALGORITHM:
MySQL有三种视图执行策略, 分别是MERGE, TEMPTABLE, UNDEFINED.
- 使用
MERGE策略,MySQL会先将输入的查询语句和视图的声明语句进行合并,然后执行合并后的语句并返回。但是如果输入的查询语句中不允许包含一些聚合函数如:MIN, MAX, SUM, COUNT, AVG, etc., or DISTINCT, GROUP BY, HAVING, LIMIT, UNION, UNION ALL, subquery。同样如果视图声明没有指向任何数据表,也是不允许的。如果出现以上任意情况, MySQL默认会使用UNDEFINED策略。 - 使用
TEMPTABLE策略,MySQL先基于视图的声明创建一张temporary table,当输入查询语句时会直接查询这张temporary table。由于需要创建temporary table来存储视图的结果集,TEMPTABLE的效率要比MERGE策略低,另外使用temporary table策略的视图是无法更新的。 - 使用
UNDEFINED策略,如果创建视图的时候不指定策略,MySQL默认使用此策略。UNDEFINED策略会自动选择使用上述两种策略中的一个,优先选择MERGE策略,无法使用则转为TEMPTABLE策略。
DEFINER
指定视图创建者。
SQL SECURITY
指定视图查询数据时的安全验证方式。
View Name
视图的名称,在MySQL中视图名和表名使用同一命名空间,这意味这视图名不能和表名重复并且要符合表名的命名规范。
Select Statement
在视图的查询声明中你可以查询所有数据库中已存在的表的数据,有以下集中规则:
- 查询声明可以在
WHERE条件中使用子查询但是不允许在FROM的来源中使用子查询。 - 查询声明中不允许引用任何变量,包括
local variables, user variables, and session variables。 - 查询声明中不允许引用
prepare statement的参数。
补充: 查询声明的From中可以引用其他视图
实例解析,现有三张表:用户(user)、课程(course)、用户课程中间表(user_course),表结构及数据如下:
-- ----------------------------
-- Table structure for `course`
-- ----------------------------
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(200) NOT NULL,
`description` varchar(500) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; -- ----------------------------
-- Records of course
-- ----------------------------
INSERT INTO `course` VALUES ('', 'JAVA', 'JAVA课程');
INSERT INTO `course` VALUES ('', 'C++', 'C++课程');
INSERT INTO `course` VALUES ('', 'C语言', 'C语言课程'); -- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`account` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
`address` varchar(255) DEFAULT NULL,
`others` varchar(200) DEFAULT NULL,
`others2` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; -- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('', 'user1', '小陈', '美国', '', '');
INSERT INTO `user` VALUES ('', 'user2', '小张', '日本', '', '');
INSERT INTO `user` VALUES ('', 'user3', '小王', '中国', '', ''); -- ----------------------------
-- Table structure for `user_course`
-- ----------------------------
DROP TABLE IF EXISTS `user_course`;
CREATE TABLE `user_course` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`userid` bigint(20) NOT NULL,
`courseid` bigint(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8; -- ----------------------------
-- Records of user_course
-- ----------------------------
INSERT INTO `user_course` VALUES ('', '', '');
INSERT INTO `user_course` VALUES ('', '', '');
INSERT INTO `user_course` VALUES ('', '', '');
INSERT INTO `user_course` VALUES ('', '', '');
INSERT INTO `user_course` VALUES ('', '', '');
INSERT INTO `user_course` VALUES ('', '', '');
这时,当我们想要查询小张上的所以课程相关信息的时候,需要这样写一条长长的SQL语句,如下:
SELECT
`uc`.`id` AS `id`,
`u`.`name` AS `username`,
`c`.`name` AS `coursename`
FROM
`user` `u`
LEFT JOIN `user_course` `uc` ON ((`u`.`id` = `uc`.`userid`))
LEFT JOIN `course` `c` ON ((`uc`.`courseid` = `c`.`id`))
WHERE
u.`name` = '小张'
但是我们可以通过视图简化操作,例如我们创建视图view_user_course如下:
-- ----------------------------
-- View structure for `view_user_course`
-- ----------------------------
DROP VIEW
IF EXISTS `view_user_course`; CREATE ALGORITHM = UNDEFINED
DEFINER = `root`@`localhost`
SQL SECURITY DEFINER
VIEW `view_user_course` AS (
SELECT
`uc`.`id` AS `id`,
`u`.`name` AS `username`,
`c`.`name` AS `coursename`
FROM
(
(
`user` `u`
LEFT JOIN `user_course` `uc` ON ((`u`.`id` = `uc`.`userid`))
)
LEFT JOIN `course` `c` ON ((`uc`.`courseid` = `c`.`id`))
)
);
创建好视图之后,我们可以直接用以下SQL语句在视图上查询小张上的所以课程相关信息,同样可以得到所需结果:
SELECT
vuc.username,
vuc.coursename
FROM
view_user_course vuc
WHERE
vuc.username = '小张'
增删改数据操作
继续,我们可以尝试在视图view_user_course上做增删改数据操作,如下:
update view_user_course set username='test',coursename='JAVASCRIPT' where id=3
遗憾的是操作失败,提示错误信息如下:
[SQL] update view_user_course set username='test',coursename='JAVASCRIPT' where id=3
[Err] 1393 - Can not modify more than one base table through a join view 'demo.view_user_course'
因为不能在一张由多张关联表连接而成的视图上做同时修改两张表的操作;
那么哪些操作可以在视图上进行呢?
视图与表是一对一关系情况:如果没有其它约束(如视图中没有的字段,在基本表中是必填字段情况),是可以进行增删改数据操作;
如我们创建用户关键信息视图view_user_keyinfo,如下:

-- ----------------------------
-- View structure for `view_user_keyinfo`
-- ----------------------------
DROP VIEW
IF EXISTS `view_user_keyinfo`; CREATE ALGORITHM = UNDEFINED DEFINER = `root`@`localhost` SQL SECURITY DEFINER VIEW `view_user_keyinfo` AS SELECT
`u`.`id` AS `id`,
`u`.`account` AS `account`,
`u`.`name` AS `username`
FROM
`user` `u`;

进行增删改操作如下,操作成功(注意user表中的其它字段要允许为空,否则操作失败):
INSERT INTO view_user_keyinfo (account, username)
VALUES
('test1', 'test1');
DELETE
FROM
view_user_keyinfo
WHERE
username = 'test1';
UPDATE view_user_keyinfo
SET username = 'updateuser'
WHERE
id = 1
视图与表是一对多关系情况:如果只修改一张表的数据,且没有其它约束(如视图中没有的字段,在基本表中是必填字段情况),是可以进行改数据操作,如以下语句,操作成功;
update view_user_course set coursename='JAVA' where id=1;
update view_user_course set username='test2' where id=3;
以下操作失败:
delete from view_user_course where id=3;
insert into view_user_course(username, coursename) VALUES('2','3');
Mysql学习笔记—视图的更多相关文章
- MySQL学习笔记一
MySQL 学习笔记 一 一.数据库简单介绍 1. 按照数据库的发展时间顺序,主要出现了以下类型数据库系统: Ø 网状型数据库 Ø 层次型数据库 Ø 关系型数据库 Ø 面向对象数据库 上面4中数据库系 ...
- MySQL学习笔记-数据库文件
数据库文件 MySQL主要文件类型有如下几种 参数文件:my.cnf--MySQL实例启动的时候在哪里可以找到数据库文件,并且指定某些初始化参数,这些参数定义了某种内存结构的大小等设置,还介绍了参数类 ...
- MySQL学习笔记-MySQL体系结构总览
MySQL体系结构总览 不管是用哪种数据库,了解数据库的体系结构都是极为重要的.MySQL体系结构主要由数据库和数据库实例构成. 数据库:物理操作系统文件或者其它文件的集合,在mysql中,数据库文件 ...
- 【mysql学习笔记整理】
/*mysql学习笔记整理*/ /*常用的数据库操作对象*/ #库的操作#创建#数据库的创建USE mysql;CREATE DATABASE db_x;#删除#删除数据库DROP DATABASE ...
- 一千行MySQL学习笔记 (转)
出处: 一千行MySQL学习笔记 /* 启动MySQL */ net start mysql /* 连接与断开服务器 */ mysql -h 地址 -P 端口 -u 用户名 -p 密码 /* 跳过权 ...
- mysql basic operation,mysql总结,对mysql经常使用语句的详细总结,MySQL学习笔记
mysql> select * from wifi_data where dev_id like "0023-AABBCCCCBBAA" ; 1.显示数据库列表.show d ...
- Mysql学习笔记(三)对表数据的增删改查。
正文内容. 这一部分是最简单的,也是最麻烦的.简单是因为其实只包括增删该插四个部分.大体上看,增加数据.删除数据.修改数据.查询数据都不麻烦啊,我们日常都是常用的.这个谁不会呢?以前在培训机构学mys ...
- Mysql学习笔记(二)数据类型 补充
原文:Mysql学习笔记(二)数据类型 补充 PS:简单的补充一下数据类型里的String类型以及列类型... 学习内容: 1.String类型 2.列类型存储需求 String类型: i.char与 ...
- Mysql学习笔记(一)数据类型
原文:Mysql学习笔记(一)数据类型 学习内容: Mysql基本数据类型. 1.数字类型.. i.整型 Mysql数据类型 含义(有符号) tinyint(m ...
随机推荐
- 项目红色感叹号eclipse因Web App Libraries中的jar包missing导致项目红色感叹号
症状: 如题 分析: 修改.更换或者删除了WEB-INF/lib中的jar包 解决方案: 右击项目>build path>Libraries 直接remove Web App Librar ...
- 从浏览器输入URL回车发生了什么
在浏览器输入url后回车,整个过程发生了什么?整个过程如果节节细述的话,那非常的复杂.我就简单的描述一下整个过程 1.查询DNS,获取域名对应的IP地址 (1).浏览器搜索自身的DNS缓存 (2).搜 ...
- MapReduce编程实例2
MapReduce编程实例: MapReduce编程实例(一),详细介绍在集成环境中运行第一个MapReduce程序 WordCount及代码分析 MapReduce编程实例(二),计算学生平均成绩 ...
- POJ 2472 106 miles to Chicago
最短路问题变形. 题意是给你一些道路,和路过时不被抓的概率. 要求找一条到达目的地时不被抓的最大概率概率. 初始 dis[]设为 1 .其余为 0 .找最大就可以. #include<cstdi ...
- 基于jQuery的让非HTML5浏览器支持placeholder属性的代码(转)
效果图:http://code.google.com/p/jquery-placeholder-js/ 演示代码:http://demo.jb51.net/js/2011/jqueryplacehol ...
- 微信小程序3 - 对象的合并
ES6中 Object.assign方法用于对象的合并,将源对象( source )的所有可枚举属性,复制到目标对象( target ). 限制: 只是浅拷贝, 即 内部对象 不会拷贝,只是 引用 ...
- 重写(Override)
重写(Override) 重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变.即外壳不变,核心重写! 重写的好处在于子类可以根据需要,定义特定于自己的行为. 也就是说子类 ...
- 请说出ArrayList,Vector, LinkedList的存储性能和特性
请说出ArrayList,Vector, LinkedList的存储性能和特性 解答:ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都 ...
- 【BZOJ】3412: [Usaco2009 Dec]Music Notes乐谱(二分)
http://www.lydsy.com/JudgeOnline/problem.php?id=3412 维护前缀和,然后直接二分即可... #include <cstdio> #incl ...
- 【c语言】将正数变成相应的负数,将负数变成相应的正数
<pre name="code" class="cpp">// 将正数变成相应的负数,将负数变成相应的正数 #include <stdio.h ...