视图、函数和过程
基础教学 1 min read

视图、函数和过程

Blog Author

MySQL 中的视图、函数和过程 —— 教学式详解与最佳实践


一、视图(View)

✅ 什么是视图?

视图(View)是数据库中一种虚拟表,本质是数据库中保存的 SQL 查询结果。当你访问一个视图时,数据库实际上是在执行它背后的 SQL 查询。

本质上是“只读的查询封装”

✅ 为什么使用视图?

优势 场景应用示例
隐藏敏感字段 只让普通用户访问 eno, ename, job 字段,隐藏工资信息
逻辑抽象、统一接口 多张表关联的复杂查询封装成一个视图,方便调用
简化权限控制 给用户授权访问视图而非底层表
保持应用与数据库结构的解耦 表结构变化只需修改视图,不影响应用逻辑

✅ 教学示例

创建视图 vw_emp_simple,仅包含基本员工信息:

create view vw_emp_simple as
select eno, ename, job, dno from tb_emp;

使用视图查询员工列表:

select * from vw_emp_simple;

删除视图:

drop view if exists vw_emp_simple;

⚠️ 不可更新的视图(Best Practice)

以下情况不能更新视图(无法用于 insert/update/delete):

  • 使用了聚合函数:sum()avg()
  • 使用 distinctgroup byunion
  • 包含子查询
  • 组合了多个视图或只读源

最佳实践:

  • 把只读查询封装成视图;
  • 更新操作仍应直接操作数据表;
  • 不要在视图中加入业务逻辑判断(如 if/else)。

二、函数(Function)

✅ 什么是函数?

MySQL 中的自定义函数类似 Python 或 JavaScript 的函数,用来封装重复使用的逻辑,可用于查询语句中直接调用并返回值

✅ 使用场景

场景 示例
统一格式化处理 统一将超长字符串截断成指定长度
可读性提升 把复杂的判断逻辑抽象为函数,提高 SQL 的可维护性
用于 SELECT 中的内联处理 SELECT fn_name(col) FROM ...

✅ 教学示例:字符串截断函数

delimiter $$


create function fn_truncate_string(
    content varchar(10000),
    max_length int unsigned
) returns varchar(10000) no sql
begin
    declare result varchar(10000) default content;
    if char_length(content) > max_length then
        set result = left(content, max_length);
        set result = concat(result, '……');
    end if;
    return result;
end $$


delimiter ;

调用函数:

select fn_truncate_string('和我在成都的街头走一走,直到所有的灯都熄灭了也不停留', 10) as short_string;

输出结果:

和我在成都的街头走一……

注意事项:

  • 修改 delimiter 语句避免语句体内的 ; 提前终止;
  • 若函数中含有 SQL 查询语句,则必须加 reads sql data
  • 尽量避免函数中操作表数据 —— 会引发性能瓶颈。

三、过程(Procedure)

✅ 什么是存储过程?

过程(Procedure)是一组预定义 SQL 的组合,一次定义、多次执行,尤其适合执行一系列逻辑操作或事务处理

区别函数:过程可以有多个输出参数、可执行事务与写操作;函数只能返回单个值。

✅ 使用场景

场景 示例
封装复杂业务逻辑 如:订单入库 + 库存检查 + 生成通知 + 写日志
提高性能 减少客户端与数据库之间交互次数
统一操作流程 薪资批量调整、数据清理、批处理逻辑等

✅ 教学示例:薪资普调过程

delimiter $$


create procedure sp_upgrade_salary()
begin
    declare flag boolean default 1;
    declare continue handler for sqlexception set flag=0;


    start transaction;


    update tb_emp set sal = sal + 300 where dno = 10;
    update tb_emp set sal = sal + 800 where dno = 20;
    update tb_emp set sal = sal + 500 where dno = 30;


    if flag then
        commit;
    else
        rollback;
    end if;
end $$


delimiter ;

调用过程:

call sp_upgrade_salary();

删除过程:

drop procedure if exists sp_upgrade_salary;

最佳实践:

  • 尽量使用事务控制流程(start transaction / commit / rollback);
  • 给过程增加异常处理器提高健壮性;
  • 避免在高并发系统中频繁调用过程,避免数据库成为性能瓶颈。

四、最佳实践总结

功能类型 建议用途 禁忌与限制
视图 简化查询,隔离权限,封装复杂逻辑 不用于更新;不要包含子查询或聚合
函数 格式处理,计算逻辑封装 不用于数据更新;避免内部 SQL 写操作
过程 多步操作封装、事务处理、批量更新 控制逻辑越复杂,维护成本越高,应适度使用

五、教学延伸:实战建议

✅ 使用场景对比

场景 使用工具
对外暴露敏感数据的子集 ✅ 使用视图
批量处理员工奖金 ✅ 使用过程
格式统一展示员工昵称 ✅ 使用函数

六、进一步学习建议

  • 初学者推荐阅读《MySQL必知必会》打基础;
  • 对于性能优化、事务控制、索引与锁机制,推荐《高性能MySQL》;
  • 熟悉事务隔离级别与并发问题:建议重点掌握 MySQL 的 REPEATABLE-READREAD COMMITTED 两种事务级别。

如需扩展学习「触发器(Trigger)」、「事件调度器(Event Scheduler)」、「游标(Cursor)」等内容,也可继续深入了解。


七、小结:何时用视图/函数/过程?

操作 适合的封装方式
查询 + 隐私保护 ✅ 视图
查询 + 格式化 ✅ 函数
多步更新 + 事务 ✅ 过程

如需可打印版学习卡片或《SQL进阶实战50例》复习文档,也可以告诉我,我可以帮你制作 ✍️