Mysql中的视图

Posted java-jun-world2099

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql中的视图相关的知识,希望对你有一定的参考价值。

1、什么是视图

通俗的讲,视图就是一条SELECT语句执行后返回的结果集。所以我们在创建视图的时候,主要的工作就落在创建这条SQL查询语句上。

视图是一种虚拟存在的表或逻辑表,视图并不在数据库中实际存在,行和列数据来自定义视图的查询总使用的表,并且是在使用视图时动态生成的。因为它与物理模式无关。数据库系统将数据库视图存储为具有连接的SQL SELECT语句。当表的数据发生变化时,视图也反映了这些数据的变化。

2、视图的特性

视图是对若干张基本表的引用,一张虚表,查询语句执行的结果,不存储具体的数据(基本表数据发生了改变,视图也会跟着改变);

可以跟基本表一样,进行增删改查操作(ps:增删改操作有条件限制);

3、视图的优点

  • 数据库视图允许简化复杂查询:数据库视图由与许多基础表相关联的SQL语句定义。 您可以使用数据库视图来隐藏最终用户和外部应用程序的基础表的复杂性。 通过数据库视图,您只需使用简单的SQL语句,而不是使用具有多个连接的复杂的SQL语句。

  • 数据库视图有助于限制对特定用户的数据访问。 您可能不希望所有用户都可以查询敏感数据的子集。可以使用数据库视图将非敏感数据仅显示给特定用户组。

  • 数据库视图提供额外的安全层。 安全是任何关系数据库管理系统的重要组成部分。 数据库视图为数据库管理系统提供了额外的安全性。 数据库视图允许您创建只读视图,以将只读数据公开给特定用户。 用户只能以只读视图检索数据,但无法更新。

  • 数据库视图启用计算列。 数据库表不应该具有计算列,但数据库视图可以这样。 假设在orderDetails表中有quantityOrder(产品的数量)和priceEach(产品的价格)列。 但是,orderDetails表没有一个列用来存储订单的每个订单项的总销售额。如果有,数据库模式不是一个好的设计。 在这种情况下,您可以创建一个名为total的计算列,该列是quantityOrderpriceEach的乘积,以表示计算结果。当您从数据库视图中查询数据时,计算列的数据将随机计算产生。

  • 数据库视图实现向后兼容。 假设你有一个中央数据库,许多应用程序正在使用它。 有一天,您决定重新设计数据库以适应新的业务需求。删除一些表并创建新的表,并且不希望更改影响其他应用程序。在这种情况下,可以创建与将要删除的旧表相同的模式的数据库视图。

4、视图的缺点

  • 性能:从数据库视图查询数据可能会很慢,特别是如果视图是基于其他视图创建的。
  • 表依赖关系:将根据数据库的基础表创建一个视图。每当更改与其相关联的表的结构时,都必须更改视图。

5、视图实例1-创建视图及查询数据操作

现有三张表:用户(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 (1, JAVA, JAVA课程);
INSERT INTO `course` VALUES (2, C++, C++课程);
INSERT INTO `course` VALUES (3, 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 (1, user1, 小陈, 美国, 1, 1);
INSERT INTO `user` VALUES (2, user2, 小张, 日本, 2, 2);
INSERT INTO `user` VALUES (3, user3, 小王, 中国, 3, 3);

-- ----------------------------
-- 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 (1, 1, 2);
INSERT INTO `user_course` VALUES (2, 1, 3);
INSERT INTO `user_course` VALUES (3, 2, 1);
INSERT INTO `user_course` VALUES (4, 2, 2);
INSERT INTO `user_course` VALUES (5, 2, 3);
INSERT INTO `user_course` VALUES (6, 3, 2);
View Code

表数据:

技术图片

这时,当我们想要查询小张上的所以课程相关信息的时候,需要这样写一条长长的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`))
        )
);

几点说明(mysql中的视图在标准SQL的基础之上做了扩展):

ALGORITHM=UNDEFINED:指定视图的处理算法;

DEFINER=`root`@`localhost`:指定视图创建者;

SQL SECURITY DEFINER:指定视图查询数据时的安全验证方式;

创建好视图之后,我们可以直接用以下SQL语句在视图上查询小张上的所以课程相关信息,同样可以得到所需结果:

SELECT
    vuc.username,
    vuc.coursename
FROM
    view_user_course vuc
WHERE
     vuc.username = 小张

 

6、视图实例2-增删改数据操作

继续,我们可以尝试在视图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);

 

 

 

参考文章:

https://www.cnblogs.com/chenpi/p/5133648.html

https://www.yiibai.com/mysql/introduction-sql-views.html

 

以上是关于Mysql中的视图的主要内容,如果未能解决你的问题,请参考以下文章

片段 A 的列表视图中的片段 B 中的新列表视图,单击 A 的列表项

如何在片段中填充列表视图?

viewpager 中的片段,未找到视图错误

如何将列表视图中的数据从一个片段发送到另一个片段

片段中的 notifyDataSetChanged() 不刷新列表视图

无法在对话框片段中的文本视图上设置文本