摘要:本文学习了如何使用DDL语句管理存储过程。
环境
Windows 10 企业版 LTSC 21H2
MySQL 5.7.40
1 简介
1.1 定义
存储过程是一组为了完成特定功能的SQL语句集合。
将常用或复杂的工作预先用SQL语句写好,将这些SQL存储起来,这个过程经过编译和优化后存储在数据库服务器中,因此称为存储过程。
1.2 优点
性能方面:
- 减少网络通信:把多条SQL语句封装成存储过程,客户端调用时只需发送一个调用命令,避免逐条发送SQL语句产生的大量网络通信,减少网络延迟和带宽占用。
- 预编译和缓存:存储过程首次调用时被预编译并缓存,后续调用直接使用缓存的编译结果,无需重复编译,提高执行效率。
安全方面:
- 权限控制:可对存储过程设置权限,用户获得执行特定存储过程的权限后,无需拥有对底层表的直接访问权限,限制用户对数据库的访问范围,降低数据被错误修改或泄露风险。
- 封装敏感操作:将复杂、敏感的数据操作逻辑(如涉及多个表更新的事务、核心商业机密计算等)封装在存储过程内部,其代码在服务器端执行,不易被篡改或被恶意用户获取敏感信息。
维护方面:
- 代码重用:存储过程可被多个应用程序或用户调用,避免在每个应用程序中重复编写相同的SQL代码,提高代码可维护性。
- 集中管理:数据库逻辑集中在服务器端,修改业务逻辑时,只需在服务器端修改存储过程,所有依赖该存储过程的应用程序都能自动使用新的逻辑,减少维护成本。
2 操作
2.1 创建
2.1.1 基础
语法:
1 | create procedure 存储过程名称([参数]) |
如果开启了二进制日志会导致执行失败,有两种解决办法:
- 使用命令:
sql 1
set global log_bin_trust_function_creators = 1;
- 修改配置文件:
my.ini 1
log_bin_trust_function_creators = 1
说明:
- 存储过程名称:存储过程的名称,默认在当前数据库中创建,可以通过
数据库名.存储过程名
指定数据库创建存储过程。 - 参数:存储过程的参数列表。
- 存储过程主体:存储过程的主体部分,包含在过程调用的时候必须执行的SQL语句。可以是单条SQL语句,也可以是被
begin
和end
包裹的复合语句块。
示例:
1 | delimiter $$ |
2.1.2 参数
参数的格式如下:
1 | [in|out|inout] 参数名 参数类型 |
支持三种类型的参数:
- 输入参数:用in关键字标识,可以传递存储过程。
- 输出参数:用out关键字标识,用于存储过程需要返回操作结果的情形。
- 输入/输出参数:用inout关键字标识,既可以充当输入参数也可以充当输出参数。
需要注意的是,参数的取名不要与数据表的列名相同,多个参数时需要用逗号分隔,没有参数时需要保留括号。
2.1.3 关键字
存储过程主体中常用的关键字:
- delimiter:修改语句结束字符。不建议使用
;
符号,因为这是默认结束字符,该符号后面的存储过程不会执行。也不建议使用\
符号,该符号是转义字符。 - begin:存储过程开始符号。
- end:存储过程结束符号。
- set:变量赋值。
- declare:声明变量和条件。
2.2 使用
语法:
1 | call 存储过程名称([参数]); |
示例:
1 | mysql> call showScore(); |
2.3 查看
查看所有存储过程:
1 | show procedure status; |
查看存储过程的创建:
1 | show create procedure 存储过程名称; |
2.4 修改
可以通过先删除存储过程,然后重新创建存储过程的方法实现修改的操作。
2.5 删除
语法:
1 | drop procedure 存储过程名称; |
示例:
1 | mysql> drop procedure showScore; |
3 变量
3.1 系统变量
系统定义的变量,根据生效范围可以分为全局变量和会话变量:
- 全局变量:在所有会话有效,修改会影响所有会话,服务重启后失效。
- 会话变量:只在当前会话有效,修改只会影响当前会话,断开连接后失效。
3.1.1 全局变量
查看变量列表:
1 | show global variables [like 搜索条件]; |
查看变量的值:
1 | select @@global.变量名; |
可以通过命令修改变量的值,修改后立即生效,服务重启后恢复默认值:
1 | set @@global.变量名 = 变量值; |
也可以通过配置文件修改变量的值,服务重启后生效。
3.1.2 会话变量
查看变量列表:
1 | show variables [like 搜索条件]; |
查看变量的值:
1 | select @@变量名; |
只能通过命令修改变量的值,修改后立即生效,断开连接后恢复默认值:
1 | set @@变量名 = 变量值; |
3.2 用户变量
用户定义的变量,根据生效范围可以分为会话变量和局部变量:
- 会话变量:只在当前会话有效,修改只会影响当前会话,断开连接后失效。
- 局部变量:只在存储过程和函数中的语句块中有效。
3.2.1 会话变量
会话变量的变量名前面需要使用@
符号进行标识。
定义:
- 直接定义:
sql 1
2set @变量名 = 变量值;
set @变量名 := 变量值; - 查询定义:
sql 1
2select @变量名 := 表达式 [from 查询语句];
select 表达式 into @变量名 [from 查询语句];
使用:
1 | select @变量名; |
3.2.2 局部变量
局部变量的变量名前面不需要使用任何标识。
声明:
1 | declare 变量名 类型 [default 值]; |
说明:
- 只能在存储过程或函数的
begin
和end
语句块中声明,并且需要在首行声明。 - 如果在声明时没有定义默认值,则使用NULL作为初始值。
赋值:
- 直接赋值:
sql 1
2set 变量名 = 变量值;
set 变量名 := 变量值; - 查询赋值:
sql 1
2select 变量名 := 表达式 [from 查询语句];
select 表达式 into 变量名 [from 查询语句];
使用:
1 | select 变量名; |
4 错误处理
4.1 默认错误处理
在执行存储过程和函数时,如果遇到错误,服务器会退出当前逻辑停止执行,并抛出错误。
如果需要在出现错误时,根据不同的错误类型进行不同的错误处理,保证程序逻辑的完整执行,就需要对错误进行处理。
4.2 错误条件
语法:
1 | declare 错误名称 condition for 错误类型; |
错误类型:
- 错误码:错误对应的数值代码。
- SQLSTATE = 错误字符串码:错误对应的字符串代码。
错误条件是可选的,其目的是为处理逻辑提供更加明确的错误名称。
4.3 处理逻辑
语法:
1 | declare 处理方式 handler for 错误类型 处理语句; |
处理方式:
- CONTINUE:表示遇到错误不处理,继续执行。
- EXIT:表示遇到错误马上退出。
- UNDO:表示遇到错误后撤回之前的操作。MySQL中暂时不支持。
错误类型:
- 错误码:错误对应的数值代码。
- SQLSTATE 错误字符串码:错误对应的字符串代码。
- 错误名称:错误条件中定义的错误名称。
- SQLWARNING:匹配所有以01开头的SQLSTATE错误。
- NOT FOUND:匹配所有以02开头的SQLSTATE错误。
- SQLEXCEPTION:匹配所有没有被SQLWARNING或NOT FOUND捕获的SQLSTATE错误。
处理语句:
- 可以通过设置变量进行处理。
- 也可以通过复合语句进行处理。
处理逻辑是必选的,匹配指定的错误条件并执行相应的处理逻辑。
5 流程控制
5.1 判断语句
5.1.1 if语句
语法:
1 | if 条件 then 命令 |
示例:
1 | delimiter $$ |
5.1.2 case语句
语法:
1 | case 变量 |
示例:
1 | delimiter $$ |
5.2 循环语句
5.2.1 while语句
当条件成立时执行循环。
语法:
1 | while 条件 do |
示例:
1 | delimiter $$ |
5.2.2 repeat语句
当条件成立时结束循环。
语法:
1 | repeat |
示例:
1 | delimiter $$ |
5.2.3 loop语句
可以在循环里判断,可以使用leave跳出循环,也可以使用iterate结束循环。
语法:
1 | 循环名称: loop |
示例:
1 | delimiter $$ |
条