14、视图(View)操作:CREATE VIEW、DROP VIEW、视图的查询、视图的局限性

视图这东西,说白了就是一张“虚拟表”。

我第一次接触视图时,觉得它挺鸡肋的——不就是把一条SELECT语句存起来吗?后来在项目中做权限控制,才发现视图是真香。你想想看,你不想让用户看到某些敏感字段,又不想每次都写一堆过滤条件,视图就是最好的中间层。

14.1 什么是视图?为什么需要它?

视图不存储数据,它只存储查询定义。每次你查询视图,数据库都会重新执行那条SELECT语句。嗯,这一点要记住,后面讲性能时会提到。

我个人习惯把视图当作“数据库的快捷方式”。比如你有一个订单表,里面包含客户姓名、手机号、地址、信用卡号。你给客服人员开权限时,肯定不想让他们看到信用卡号。这时候,创建一个视图,只暴露姓名、地址和订单金额,就安全多了。

核心概念:视图 = 存储的查询。它不占物理空间(除了定义本身),但能像表一样被查询。

14.2 CREATE VIEW:创建视图

语法很简单,我直接上代码:

CREATE VIEW view_name AS
SELECT column1, column2, ...
FROM table_name
WHERE condition;

举个例子。假设我们有一个员工表 employees

CREATE TABLE employees (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    department VARCHAR(50),
    salary DECIMAL(10,2),
    phone VARCHAR(20)
);

现在,我想创建一个视图,只暴露姓名和部门,隐藏工资和电话:

CREATE VIEW v_employee_public AS
SELECT id, name, department
FROM employees;

查询这个视图:

SELECT * FROM v_employee_public;

结果只显示三列,工资和电话被屏蔽了。我在项目中做过类似的视图,用来给外包团队开放数据查询权限,效果很好。

小技巧:视图名最好加个前缀,比如 v_view_,一眼就能和表区分开。我习惯用 v_,简洁明了。

14.3 视图的查询:和查表一样简单

视图的查询语法和普通表完全一样:

SELECT * FROM v_employee_public WHERE department = '技术部';

你甚至可以基于视图再创建视图(虽然我不建议嵌套太深,后面会讲原因):

CREATE VIEW v_tech_employees AS
SELECT * FROM v_employee_public WHERE department = '技术部';

查询这个嵌套视图:

SELECT * FROM v_tech_employees;

嗯,这里要注意:每次查询视图,底层都会执行原始SQL。如果原始SQL很复杂,视图查询也会慢。我曾经接手过一个项目,视图嵌套了四层,查询一次要十几秒……后来全部重写了。

14.4 DROP VIEW:删除视图

删除视图不会影响底层表的数据,放心删:

DROP VIEW v_tech_employees;

如果要删除的视图不存在,会报错。你可以加个判断:

DROP VIEW IF EXISTS v_tech_employees;

我个人习惯在重构数据库时,先把所有视图删掉再重建。这样能避免一些奇怪的依赖问题。

警告:删除视图前,确认没有其他视图或存储过程依赖它。否则你会收到一堆报错。我曾经在线上环境直接DROP了一个视图,结果下游三个报表全挂了……嗯,从那以后我每次删视图前都会先查一下依赖关系。

14.5 视图的局限性:别把它当万能药

视图虽然好用,但坑也不少。我列几个常见的:

  • 性能问题:视图不存储数据,每次查询都重新执行SQL。如果视图基于多表JOIN或复杂聚合,查询会很慢。
  • 更新限制:不是所有视图都能更新数据。比如包含DISTINCT、GROUP BY、UNION、子查询的视图,通常不能执行INSERT、UPDATE、DELETE。
  • 嵌套深度:视图套视图,套多了连你自己都搞不清数据来源。我建议最多嵌套两层。
  • 调试困难:视图出错了,你很难直接定位是视图本身的问题,还是底层表的问题。

举个例子,下面这个视图就不能直接更新:

CREATE VIEW v_dept_salary AS
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department;

如果你试图执行:

UPDATE v_dept_salary SET avg_salary = 10000 WHERE department = '技术部';

数据库会直接报错。因为 avg_salary 是聚合计算出来的,不是真实列。

记住:视图适合“读多写少”的场景。如果你需要频繁更新数据,直接用表,别绕弯子。

14.6 知识体系图:视图操作全景

下面这张图总结了视图的核心操作和注意事项,我建议你保存下来,写代码时对照着看:

视图(View) CREATE VIEW 查询视图 DROP VIEW 局限性:性能、更新限制、嵌套、调试 避坑指南 • 视图不存储数据,每次查询都重新执行SQL • 包含聚合、DISTINCT、UNION的视图无法更新 • 嵌套视图最多两层,否则性能急剧下降

14.7 实战建议:什么时候用视图?

我总结了几种适合用视图的场景:

场景 说明 示例
权限控制 隐藏敏感字段,只暴露必要数据 隐藏工资、手机号、身份证
简化复杂查询 把多表JOIN封装成视图,方便重复使用 订单+客户+商品三表关联
数据一致性 多个地方使用同一个查询逻辑,修改时只改视图 报表统计口径统一
兼容旧系统 表结构改了,但旧接口不想动,用视图做映射 字段改名后创建别名视图

我的经验:视图最适合做“读接口”。如果你需要写数据,或者对性能要求极高,直接操作底层表更靠谱。视图不是银弹,用对了是利器,用错了是累赘。

好了,视图的内容就这些。记住:视图是虚拟表,不存数据,每次查询都重新跑SQL。创建时注意权限和性能,删除时注意依赖关系。做到这几点,视图就是你数据库工具箱里的一把好手。


公众号:蓝海资料掘金营,微信deep3321