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');
 
 
 
 
 
 
参考:

最新文章

  1. 冲刺阶段 day13
  2. js控制div颜色
  3. maven命令大全
  4. JAVA的序列化与反序列化
  5. Intent传递数据
  6. DIV遮罩层传值
  7. 自制单片机之十一……模数转换IC ADC0809
  8. 关于Linux虚拟化技术KVM的科普 科普一(先用起来!)
  9. Linux下使用http协议下载文件
  10. Maven 项目 无缘无故报错:版本冲突,其他机器上正常-提交的时候报冲突怎么也解决不掉
  11. python基础——dict和set(字典和集合)
  12. vue注册和简单使用
  13. go test 测试用例那些事
  14. iOS开发-NSUndoManager撤销(undo)和重做(redo)
  15. RN animated帧动画
  16. FastDFS安装教程
  17. java整理的一些面试资料
  18. 用于HTML5移动开发的10大移动APP开发框架【转】
  19. Kibana访问权限控制
  20. SEO从理论到实践

热门文章

  1. 排查PHP-FPM占用CPU过高
  2. Hive学习笔记——基本配置及测试
  3. mvn命令若干:
  4. js 数组取出最大值最小值和平均值的方法
  5. easyUI的column的field的颜色属性
  6. css3学习笔记(一)
  7. 第二百三十八节,Bootstrap输入框和导航组件
  8. VS2008让Release配置也能调试起来~
  9. requestAnimationFrame 实现JS动画
  10. Android 实现个性的ViewPager切换动画 实战PageTransformer(兼容Android3.0下面)