当前位置: 首页 > news >正文

数据库系统概论(十五)详细讲解数据库视图

数据库系统概论(十五)数据库视图

  • 前言
  • 一、什么是视图?
  • 二、视图的作用
    • 1. 保护数据安全
    • 2. 屏蔽表结构变化
    • 3. 简化复杂查询
    • 4. 多角度展示数据
  • 三、如何创建视图?
    • 语法格式:
    • 5种常见视图类型:
  • 四、更新视图的限制
  • 五、如何删除视图
  • 六、查询视图
    • 1. 查询视图的基本用法
    • 2. 系统如何执行视图查询?
    • 3、复杂视图查询的坑
      • 场景:用分组视图查平均成绩≥90分的学生
        • 正确做法1:直接对基表查询(用HAVING)
        • 正确做法2:用派生表模拟视图(临时视图)
    • 4、不同数据库的差异
  • 七、更新视图
    • 1. 什么是更新视图?
    • 2. 如何更新视图?
      • (1)修改数据
      • (2)插入数据
      • (3)删除数据
    • 3. 更新视图的“安全锁”:WITH CHECK OPTION
    • 4. 哪些视图不能更新?
      • (1)复杂视图
      • (2)不同数据库的限制差异


前言

  • 在前几期博客中,我们探讨了 SQL 连接查询,单表查询,嵌套查询,集合查询,基于派生表的查询,数据插入,修改与删除,空值的处理技术等知识点。
  • 从本节开始,我们将深入讲解 SQL 中视图的知识点。

我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的数据库系统概论专栏
https://blog.csdn.net/2402_83322742/category_12911520.html?spm=1001.2014.3001.5482


一、什么是视图?

视图就像数据库中的“虚拟表格”,它的数据来自真实的表(基表),但本身不存储真实数据,只存储“如何从基表取数据的规则”。

  • 举个例子
    基表是“学生表”(包含所有学生信息),视图可以是“信息管理专业学生视图”,只显示该专业学生的部分信息(如学号、姓名、专业)。

  • 视图的特点

    1. 虚表:数据字典只存定义,不存实际数据
    2. 动态更新:基表数据变了,视图查询结果也会变。

二、视图的作用

1. 保护数据安全

  • 作用控制用户能看到的数据范围,隐藏敏感信息
    • 举例:员工表中,普通员工只能通过视图看到姓名和部门,而工资、银行卡号等机密字段被“过滤”掉。
  • 原理:通过视图限制查询的字段或行,就像给数据加了一层“滤镜”,非授权数据无法被访问。

2. 屏蔽表结构变化

  • 作用:当数据库表结构调整(如重命名字段、拆分表)时,视图可以保持对外接口不变,避免影响应用程序。
    • 举例:原表Student有字段S_age,改为S_birthdate后,通过视图依然以S_age名称提供年龄数据(视图内部转换计算),程序无需修改代码
  • 原理:视图作为“中间层”,隔离了底层表的变化。

3. 简化复杂查询

  • 作用:将常用的复杂查询(如多表连接、计算字段)定义为视图,用户直接查询视图即可,无需重复写冗长SQL。
    • 举例:查询“学生姓名+课程成绩”需要连接StudentSC表,定义视图Student_Score后,直接查视图就行,不用每次写JOIN语句。
  • 原理:视图相当于把复杂操作“打包”成一个快捷按钮,点击即可得到结果,减少重复劳动。

4. 多角度展示数据

  • 作用:同一批数据,不同用户可以通过不同视图看到不同角度的内容。
    • 举例:销售数据中,普通员工 视图显示“个人业绩明细”,经理视图 显示“部门业绩汇总”,数据来源相同但展示形式不同。
  • 原理:视图就像“数据滤镜”,根据用户需求过滤、重组数据,让不同人看到自己需要的信息。

三、如何创建视图?

语法格式:

CREATE VIEW 视图名 [(列名1, 列名2, ...)] -- 可选,定义视图的列名
AS
子查询 -- 从基表取数据的规则(不能有ORDER BY和DISTINCT)
[WITH CHECK OPTION] -- 可选,限制通过视图更新数据时必须符合子查询条件

5种常见视图类型:

  1. 行列子集视图(单表筛选)
    场景:从“学生表”筛选“信息管理专业”学生,只显示部分列。

    CREATE VIEW IS_Student AS
    SELECT Sno, Sname, Ssex, Smajor -- 选这几列
    FROM Student -- 基表
    WHERE Smajor = '信息管理与信息系统'; -- 筛选条件
    
    • 说明:省略列名时,视图列名和子查询的列名一致。
  2. 多表视图(多表连接)
    场景:查询“信息管理专业学生选81001课程的成绩”(学生表+选课表连接)。

    CREATE VIEW IS_C1(Sno, Sname, Grade) AS -- 显式指定列名
    SELECT Student.Sno, Sname, Grade -- 选学号、姓名、成绩
    FROM Student, SC -- 两张表
    WHERE Student.Sno = SC.Sno -- 连接条件AND Smajor = '信息管理与信息系统' -- 专业筛选AND SC.Cno = '81001'; -- 课程筛选
    
  3. 基于视图的视图(视图嵌套)
    场景:在“IS_C1视图”基础上,再筛选“成绩≥90分”的学生。

    CREATE VIEW IS_C2 AS -- 直接基于已有视图创建
    SELECT Sno, Sname, Grade 
    FROM IS_C1 
    WHERE Grade >= 90;
    
  4. 带表达式的视图(计算列)
    场景:计算学生年龄(用出生日期算年龄)。

    CREATE VIEW S_AGE(Sno, Sname, Sage) AS -- 必须显式指定列名(含计算列)
    SELECT Sno, Sname, TIMESTAMPDIFF(YEAR, Sbirthdate, CURDATE()) -- 计算年龄的表达式
    FROM Student;
    
  5. 分组视图(聚合函数)
    场景:统计每个学生的平均成绩。

    CREATE VIEW S_GradeAVG(Sno, Gavg) AS -- 显式指定列名(含聚合列)
    SELECT Sno, AVG(Grade) -- 按学号分组,算平均成绩
    FROM SC 
    GROUP BY Sno;
    

四、更新视图的限制

  • 一般情况:视图主要用于查询,直接增删改可能受限(因视图可能关联多表或包含表达式)。
  • 强制限制:创建视图时加 WITH CHECK OPTION,可确保通过视图插入/修改的数据符合视图定义的条件。
    CREATE VIEW IS_Student AS
    SELECT ... FROM Student WHERE Smajor='信息管理与信息系统'
    WITH CHECK OPTION; -- 插入时若专业不是该专业,会报错
    

五、如何删除视图

语法

DROP VIEW 视图名 [CASCADE]; -- CASCADE(级联删除):删除依赖它的其他视图
  • 例子
    • 单删视图:DROP VIEW S_AGE;
    • 级联删(如IS_C1视图被IS_C2依赖):
      DROP VIEW IS_C1 CASCADE; -- 同时删除IS_C1和IS_C2
      
  • 注意:不同数据库差异大!
    • KingBase支持CASCADE级联删除;
    • MySQL不支持,删除IS_C1后,IS_C2会失效但不会自动删除,需手动处理。

六、查询视图

1. 查询视图的基本用法

查询视图就像查询普通表一样简单,直接写 SELECT 语句即可,语法和查基表完全一致。

  • 举例
    有一个“信息管理专业学生视图”(IS_Student),想查其中年龄≤20岁的学生学号和出生日期:
    SELECT Sno, Sbirthdate FROM IS_Student 
    WHERE TIMESTAMPDIFF(YEAR, Sbirthdate, CURDATE()) <= 20;
    
    看起来和查基表没区别,但背后系统会做一些转换。

2. 系统如何执行视图查询?

当你查询视图时,数据库系统会做以下三件事

  1. 检查有效性:确认视图是否存在,列名是否正确。
  2. 转换成基表查询(核心步骤):
    • 有一个视图表他的定义是:
      CREATE VIEW IS_Student AS 
      SELECT Sno,... FROM Student WHERE Smajor='信息管理与信息系统';
      
    • 系统会把它的视图查询 “翻译”成基表查询
      SELECT Sno, Sbirthdate FROM Student 
      WHERE Smajor='信息管理与信息系统'  -- 视图定义的条件AND TIMESTAMPDIFF(YEAR, Sbirthdate, CURDATE()) <= 20;  -- 你加的条件
      
  3. 执行翻译后的SQL:直接对基表(Student表)执行查询,返回结果。

核心逻辑:视图查询本质是“披着视图外衣的基表查询”,系统会先把视图“还原”成基表的SQL,再执行。

3、复杂视图查询的坑

场景:用分组视图查平均成绩≥90分的学生

假设你有一个分组视图 S_GradeAVG(存储每个学生的学号和平均成绩):

CREATE VIEW S_GradeAVG(Sno, Gavg) AS 
SELECT Sno, AVG(Grade) FROM SC GROUP BY Sno;

错误做法:直接对视图用 WHERE 过滤平均成绩

SELECT * FROM S_GradeAVG WHERE Gavg >= 90;  -- 看似正确,实则错误!

系统翻译后

SELECT Sno, AVG(Grade) FROM SC 
WHERE AVG(Grade) >= 90  -- ❌ WHERE子句不能用聚集函数(AVG)
GROUP BY Sno;

报错原因WHERE 只能过滤行数据,不能直接用聚集函数(如AVG、SUM),聚集函数要配合 HAVING 使用。

正确做法1:直接对基表查询(用HAVING)
SELECT Sno, AVG(Grade) AS Gavg FROM SC 
GROUP BY Sno 
HAVING Gavg >= 90;  -- ✅ 用HAVING过滤分组后的结果
正确做法2:用派生表模拟视图(临时视图)
SELECT * FROM (SELECT Sno, AVG(Grade) AS Gavg FROM SC GROUP BY Sno
) AS 临时视图名  -- 派生表,执行完就消失
WHERE Gavg >= 90;

4、不同数据库的差异

  1. 视图查询的兼容性
    • 大部分数据库(如KingBase)对简单视图(行列子集视图)能正确翻译,但复杂视图(如分组视图)可能报错。
    • MySQL比较“宽容”
      • 对分组视图的 WHERE Gavg >= 80 可能能执行(内部做了优化),但本质上不推荐这么写。
      • 直接对基表用 WHERE AVG(Grade) 会报错:
        SELECT Sno, AVG(Grade) FROM SC 
        WHERE AVG(Grade) >= 90 GROUP BY Sno;  -- ❌ MySQL报错!
        

七、更新视图

1. 什么是更新视图?

通过视图修改基表的数据(增、删、改)。

  • 本质:视图本身没有数据,更新视图时,数据库会把操作“翻译”成对基表的更新(视图消解)。
  • 举例:修改视图中的学生姓名,其实是在修改基表(学生表)中的真实数据。

2. 如何更新视图?

(1)修改数据

场景:将IS_Student视图中学号为20180005的学生姓名改为“刘新奇”。

UPDATE IS_Student SET Sname='刘新奇' WHERE Sno='20180005';

背后发生了什么?
数据库自动将视图查询转换为基表操作:

UPDATE Student SET Sname='刘新奇' 
WHERE Sno='20180005' AND Smajor='信息管理与信息系统'; -- 视图定义的条件自动保留

(2)插入数据

场景:向IS_Student视图中插入一个信息管理专业的学生。

INSERT INTO IS_Student VALUES ('20180207','赵新','男','2001-7-19','信息管理与信息系统');

背后发生了什么?
直接插入基表(Student表),专业字段自动符合视图条件:

INSERT INTO Student VALUES ('20180207','赵新','男','2001-7-19','信息管理与信息系统');

(3)删除数据

场景:删除IS_Student视图中学号为20180207的学生。

DELETE FROM IS_Student WHERE Sno='20180207';

背后发生了什么?
从基表删除符合条件的记录(同时满足学号和专业条件):

DELETE FROM Student WHERE Sno='20180207' AND Smajor='信息管理与信息系统';

3. 更新视图的“安全锁”:WITH CHECK OPTION

作用:确保通过视图插入/修改的数据必须符合视图定义的条件,防止“脏数据”进入。

  • 创建视图时加锁
    CREATE VIEW IS_Student AS
    SELECT ... FROM Student WHERE Smajor='信息管理与信息系统'
    WITH CHECK OPTION; -- 强制要求插入/修改的记录必须是该专业
    
  • 举例
    若尝试插入其他专业的学生:
    INSERT INTO IS_Student VALUES ('20180208','钱明','男',...,'计算机科学与技术');
    
    结果:直接报错,因为违反了WITH CHECK OPTION的条件(专业必须是信息管理与信息系统)。

4. 哪些视图不能更新?

(1)复杂视图

  • 包含多表连接的视图
    例:基于学生表和选课表连接创建的视图,无法确定更新哪张表的数据。
  • 包含聚集函数的视图(如AVG、SUM):
    例:S_GradeAVG视图(平均成绩),更新平均分会导致逻辑混乱(系统不知道要改哪些原始成绩)。
    UPDATE S_GradeAVG SET Gavg=90 WHERE Sno='20180001'; -- ❌ 报错!
    
  • 分组视图(含GROUP BY):
    同上,系统无法将分组后的更新映射到基表的具体行。

(2)不同数据库的限制差异

  • 行列子集视图(单表简单筛选):通常可以更新(如IS_Student视图)。
  • 非行列子集视图:不同数据库处理不同,例如:
    • MySQL可能允许部分更新,但不推荐;
    • KingBase等严格数据库会直接禁止复杂视图的更新。

以上就是这篇博客的全部内容,下一篇我们将继续探索更多精彩内容。

我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的数据库系统概论专栏
https://blog.csdn.net/2402_83322742/category_12911520.html?spm=1001.2014.3001.5482

非常感谢您的阅读,喜欢的话记得三连哦

在这里插入图片描述

相关文章:

  • 【Linux】pthread多线程基础
  • Java集合初始化:Lists.newArrayList vs new ArrayList()
  • PART 6 树莓派小车+QT (TCP控制)
  • 开发的几种格式,TCP的十个重要机制
  • Figma 与 Cursor 深度集成的完整解决方案
  • 从【0-1的HTML】第1篇:HTML简介
  • SQL 执行顺序详解
  • PostgreSQL pgrowlocks 扩展
  • LeetCode 高频 SQL 50 题(基础版) 之 【高级查询和连接】· 上
  • SQL: 窗口滑动(Sliding Window)
  • C++前缀和介绍
  • MyBatisPlus--条件构造器及自定义SQL详解
  • Linux(信号)
  • PostgreSQL的扩展 insert_username
  • 数据库系统概论(十四)详细讲解SQL中空值的处理
  • 连接天际,守护通信—5G航天时代的电流守卫与浪涌盾牌
  • Caliper压力测试
  • vue · 路由传参query和params
  • Codeforces Round 1028 (Div. 2)(A-D)
  • 深入理解 Linux 文件系统与日志文件分析
  • 注册网站查询/网络营销课程培训机构
  • win系统做网站/建站网站关键词优化
  • iis网站伪静态/新平台怎么推广
  • wordpress 图片不显示/福建seo网站
  • 番禺品牌型网站建设/网络推广主要内容
  • 网站开发周期表/百度推广的定义