一、先拆解这段SQL代码

这段代码是标准的视图创建语句,我们逐行拆解它的作用:

CREATE OR REPLACE VIEW v_usa_vendors AS 
    SELECT vend_id,vend_name,vend_city,vend_state
    FROM main.Vendors 
    WHERE vend_country = 'USA';
  1. CREATE OR REPLACE VIEW v_usa_vendors AS

    • 核心动作:创建一个名为 v_usa_vendors 的视图;如果该视图已经存在,就直接覆盖更新它的定义,无需先删除再重建。
    • 命名规范:前缀 v_ 是行业通用约定,用来和普通数据表区分,一眼就能识别这是视图。
  2. SELECT vend_id,vend_name,vend_city,vend_state

    • 定义视图要暴露的列:只保留供应商编号、名称、城市、州这4个字段,基表中其他列(比如供应商银行账号、联系人电话)不会出现在视图里。
  3. FROM main.Vendors

    • 指定数据来源:视图的数据全部来自 main 架构下的 Vendors 供应商表,这个表也叫基表。
  4. WHERE vend_country = 'USA'

    • 定义行级筛选规则:只保留国家为美国的供应商记录,其他国家的数据会被完全过滤掉。

二、视图的本质:到底什么是视图

视图(View)是SQL中的虚拟表,这是理解它的第一性原理:

  1. 视图不存储任何真实数据:它本身只是一段被命名、被保存起来的 SELECT 查询语句,没有自己的数据文件。你看到的所有行和列,都来自底层基表的实时计算。
  2. 使用上和普通表完全一致:你可以像查询普通表一样对视图执行 SELECT、加筛选条件、关联其他表,语法没有任何区别。

用会计场景做类比:

  • 基表 Vendors 相当于企业的全套供应商档案台账,里面记录了所有供应商的全部信息,是原始数据的载体。
  • 视图 v_usa_vendors 相当于你定制的美国供应商专用报表模板:模板里提前设好了筛选条件和显示字段,每次打开模板都会自动从台账里取最新数据生成结果;模板本身不存数据,数据变更都发生在原始台账上。

三、视图的核心价值:为什么要用视图

视图是典型的“逻辑封装工具”,核心价值不在性能,而在简化、安全、统一口径,主要有4个作用:

1. 简化复杂查询,降低使用门槛

把多表关联、多层嵌套、复杂计算的SQL封装成视图,业务人员不用理解底层表结构,直接 SELECT * FROM 视图 就能拿到结果。 比如你这个美国供应商视图,后续任何人要查美国供应商,都不用再记筛选条件和字段名,直接查视图即可。

2. 数据权限管控,实现字段/行级脱敏

这是企业级系统里视图最常用的场景:

  • 列级安全:隐藏敏感字段。比如供应商表有银行账号、联系人手机号,视图只暴露名称和地址,普通员工只能访问视图,接触不到敏感数据。
  • 行级安全:限制可见数据范围。比如这个视图只让美国区运营看到美国的供应商,看不到其他国家的供应商数据。 就像会计岗位的权限分离:出纳只能看资金账,看不到成本利润明细,视图就是实现这种权限隔离的常用手段。

3. 统一数据口径,避免统计偏差

当多个报表、多个部门都用到同一份逻辑时,把逻辑固化成视图,保证所有人取数规则一致。 比如“美国供应商”的定义,如果每个人自己写SQL,可能有人漏了筛选条件、有人用了不同的字段,最终统计结果对不上。视图定义一次,全局复用,从根源上统一口径。

4. 兼容上层应用,屏蔽表结构变更

如果底层基表因为业务重构拆分、合并了字段,可以通过视图保持对外的表结构不变,上层应用、报表系统不用修改代码,实现平滑过渡。 比如原来的 Vendors 表拆成了供应商基础表和供应商地址表,你可以通过视图把两表关联起来,对外仍然呈现原来的字段结构,老程序无需改动。


四、视图的底层执行原理

很多初学者会误以为“视图是预编译的,查询更快”,这是非常常见的误区。

当你执行:

SELECT * FROM v_usa_vendors WHERE vend_state = 'CA';

数据库内部的实际执行步骤是:

  1. 解析SQL,识别出 v_usa_vendors 是视图;
  2. 从系统数据字典中取出视图的定义语句(也就是你创建视图时写的那段SELECT);
  3. SQL合并重写:把外层的查询条件和视图内部的查询逻辑合并成一条完整SQL,等价于:
    SELECT vend_id,vend_name,vend_city,vend_state
    FROM main.Vendors
    WHERE vend_country = 'USA' AND vend_state = 'CA';
    
  4. 查询优化器对这条合并后的SQL生成执行计划,然后访问基表取数。

结论:普通视图不会提升查询性能,它的执行效率和你直接写完整SQL完全一样。如果视图里嵌套了视图(视图A里面又引用了视图B),反而会增加优化器的解析成本,可能导致性能下降。


五、视图的常见操作

1. 查询视图

和普通表完全一致,支持筛选、排序、分组:

-- 查询美国加州的供应商
SELECT vend_name, vend_city 
FROM v_usa_vendors 
WHERE vend_state = 'CA'
ORDER BY vend_name;

2. 更新视图(有严格限制)

视图本身没有数据,对视图执行 INSERT/UPDATE/DELETE,本质是修改底层基表的数据。 但只有“简单视图”才支持更新,必须同时满足:

  • 只基于单张基表,没有多表JOIN;
  • 没有聚合函数(SUM/COUNT/AVG等)、没有GROUP BY、没有DISTINCT、没有UNION;
  • 没有计算列、没有子查询。

你写的这个 v_usa_vendors 就属于可更新视图,执行:

UPDATE v_usa_vendors SET vend_city = 'New York' WHERE vend_id = 1001;

会直接修改 Vendors 基表中对应行的数据。

反之,如果视图是多表关联、带分组统计的,就无法更新——数据库不知道该把修改映射到基表的哪一行。

3. 删除视图

DROP VIEW IF EXISTS v_usa_vendors;

删除视图只会删除视图的定义,不会影响底层基表的任何数据。


六、优缺点与最佳实践

优点

  • 代码复用,减少重复SQL编写
  • 精细化权限控制,保障数据安全
  • 屏蔽底层复杂度,降低业务人员使用门槛
  • 统一数据口径,减少统计不一致问题

缺点

  • 不存储数据,复杂视图每次查询都要重新计算,性能取决于基表和索引
  • 多层嵌套视图会严重劣化性能,且排查问题困难
  • 可更新性限制多,复杂视图无法直接写数据
  • 容易隐藏复杂度,维护者可能误以为视图很简单,忽略底层的多表关联逻辑

最佳实践

  1. 命名统一加前缀(如 v_),和物理表区分开;
  2. 定义视图时明确写列名,禁止用 SELECT *,避免基表加字段后视图不同步;
  3. 尽量不要嵌套视图,最多一层,禁止三层以上嵌套;
  4. 高频访问、数据实时性要求不高的场景,优先用物化视图(Materialized View,会真实存储数据,定时刷新)而非普通视图;
  5. 视图只做逻辑封装,不要在视图里写过于复杂的业务计算。