• 【数据库入门到精通】mysql的存储过程实战


    前言

    在这里插入图片描述

    🏠个人主页:我是沐风晓月
    🧑个人简介:大家好,我是沐风晓月,双一流院校计算机专业,阿里云社区专家博主😉😉
    💕 座右铭: 先努力成长自己,再帮助更多的人 ,一起加油进步🍺🍺🍺
    💕欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信😘

    可以关注我的云原生社区云原生社区
    也可以关注我的英语社区从零开始学英语

    mysql存储过程的概念

    百科中超难理解的版本:

    MySQL 的存储过程(Stored Procedures)是一组预先定义好的 SQL 语句集合,这些语句会经过编译并存储在数据库中,可以在需要时被调用执行。存储过程可以接受输入参数、返回输出结果,并且具有复杂的逻辑处理能力。

    修正后的版本:

    存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。

    还是不理解的话,看这里:

    存储过程,你可以理解为类似于shell脚本中的函数,只不过函数是一组shell命令的组合,而存储过程是一组SQL语句的组合。

    存储过程的优缺点

    1. 存储过程的优点

    1. 提高性能:存储过程在数据库服务器端执行,减少了与数据库服务器之间的通信开销。相比于每次向服务器发送一个查询请求,使用存储过程可以将复杂的逻辑封装在数据库内部,并通过一次调用执行多个 SQL 语句,从而减少了网络流量和服务器资源开销,提高了执行效率。

    2. 重用性和模块化:存储过程可以在多个应用程序中重复使用,避免了重复编写相同的 SQL 语句逻辑。它们提供了一种模块化的方式来组织和管理数据库逻辑,使得开发人员可以专注于业务逻辑层面的实现,提高了开发效率。

    3. 降低代码复杂性:存储过程可以封装复杂的业务逻辑和数据操作,并暴露简单的接口供应用程序调用。这样可以将复杂性从应用程序中移除,使得应用程序的代码变得更简洁、清晰,易于维护和理解。

    4. 数据安全性:存储过程可以对用户的权限进行控制,为数据库提供了一种更强大的访问控制机制。通过存储过程,可以限制对特定数据表和数据字段的访问,确保只有授权的用户能够执行特定的操作,提升了数据库的安全性。

    5. 事务管理和数据一致性:存储过程可以嵌入事务语句,提供了对复杂操作的原子性执行和数据一致性的保证。通过使用存储过程,可以确保在一次调用中执行的所有 SQL 操作要么全部成功提交,要么全部回滚,避免了因为异常情况导致的数据不一致问题。

    6. 性能优化和查询优化:存储过程可以对复杂的查询语句进行优化,通过使用合适的索引、查询重写和查询优化技术,提高查询性能。此外,存储过程还可以缓存查询计划,避免了每次执行查询时重新生成查询计划的开销,提升了查询效率。

    2. 存储过程的缺点

    1. 可移植性差;
    2. 对于简单的SQL语句,存储过程没什么优势;
    3. 如果存储过程中不一定会减少网络传输;
    4. 如果只有一个用户使用数据库,那么存储过程对安全也没什么影响;
    5. 团队开发时需要先统一标准,否则后期维护成本大;
    6. 在大并发量访问的情况下,不宜写过多涉及运算的存储过程;
    7. 业务逻辑复杂时,特别是涉及到对很大的表进行操作的时候,不如在前端先简化业务逻辑。

    定义存储过程

    1. 创建存储过程的语法

    # 声明存储过程
    create procedure 过程名(参数1,参数2....# 存储过程的开始符号begin ,结束符合end
    begin 
    sql语句;
    sql语句;
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    需要注意的是: 创建存储过程之前我们必须修改mysql语句默认结束符“ ; 要不然我们不能创建成功。

    使用delimiter可以修改执行符号:

     DELIMITER $$ 
    或者
      DELIMITER //
    
    • 1
    • 2
    • 3

    2. 创建存储过程案例

    这里的book库是我自己的数据库。

    mysql>use book;
    注意: 必须先进入数据库 book
    
    mysql> delimiter %  这样结束符就为%
    mysql> create procedure selCg()
        -> begin
        -> select * from category;
        -> end %
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    也可以这么写:

    mysql> create procedure selCg() begin  select * from category; end%
    
    • 1

    3. 调用存储过程

    call 过程名(参数1,参数2);
    
    • 1

    调用案例:

    mysql> call selCg()%
    +---------+---------------+
    | bTypeId | bTypeName     |
    +---------+---------------+
    |       1 | windows应用   |
    |       2 | 网站          |
    |       3 | 3D动画        |
    |       4 | linux学习     |
    |       5 | Delphi学习    |
    |       6 | 黑客          |
    |       7 | 网络技术      |
    |       8 | 安全          |
    |       9 | 平面          |
    |      10 | AutoCAD技术   |
    +---------+---------------+
    10 rows in set (1.25 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    用完记得切换回来:

    mysql> delimiter ;
    
    • 1

    4. 删除存储过程

    语法:

    drop procedure sp_name;
    
    • 1

    案例:

    mysql> drop procedure selCg ;
    Query OK, 0 rows affected (0.13 sec
    
    • 1
    • 2

    存储过程的参数类型

    1. In参数 传入参数

    特点:读取外部变量值,且有效范围仅限存储过程内部。

    use book;

    mysql> delimiter //
    mysql> create procedure demo1(in abc int)
        -> begin
        -> select abc;
        -> set abc=66;
        -> select abc;
        -> end;
        -> //
    Query OK, 0 rows affected (0.43 sec)
    mysql> delimiter ;  使用完马上恢复默认的
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    传入值进去:

    mysql> call demo1(60);
    +------+
    | abc  |
    +------+
    |   60 |
    +------+
    1 row in set (0.03 sec)
    
    +------+
    | abc  |
    +------+
    |   66 |
    +------+
    1 row in set (0.04 sec
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    会看到传值进去后,先输入第一个select是60,在后面又重新做了赋值,是66,一共两个值。

    也可以传变量进去:

    mysql定义变量方法:
    语法格式: set @字段名=值
    例如

     set @num=1
    mysql> set @y=1;    局部变量
    
    • 1
    • 2

    我们先来看一个变量的使用案例:

    mysql> set @y=1;
    Query OK, 0 rows affected (0.10 sec)
    
    mysql> select @y
        -> ;
    +------+
    | @y   |
    +------+
    |    1 |
    +------+
    1 row in set (0.54 sec)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    接下来我们传入变量到存储过程:

    mysql> call demo1(@y);
    +------+
    | abc  |
    +------+
    |    1 |
    +------+
    1 row in set (0.15 sec)
    
    +------+
    | abc  |
    +------+
    |   66 |
    +------+
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    实战案例:
    定义一个存储过程 getOneBook,当输入某书籍 id 后,可以调出对应书籍记录

    mysql>delimiter //
    mysql> create procedure getOneBook2(in book int) begin select bid,bname,price from books where bId=book; end//
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> call getOneBook2(3) //
    +-----+-----------------------------+-------+
    | bid | bname                       | price |
    +-----+-----------------------------+-------+
    |   3 | 网络程序与设计-asp         |    43 |
    +-----+-----------------------------+-------+
    1 row in set (0.59 sec)
    
    Query OK, 0 rows affected (0.59 sec)
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2. Out参数 传出参数

    特点:不读取外部变量值,在存储过程执行完毕后保留新值

    mysql> 
    mysql> use book
    Reading table information for completion of table and column names
    You can turn off this feature to get a quicker startup with -A
    
    Database changed
    mysql> 
    mysql> delimiter //
    mysql> create procedure pout(out p_out int)
        -> begin
        -> select p_out;
        -> set p_out=2;
        -> select p_out;
        -> end;
        -> //
    Query OK, 0 rows affected (0.04 sec)
    
    mysql> delimiter ;
    mysql> set @p_out=1
        -> ;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> call pout(@p_put);
    +-------+
    | p_out |
    +-------+
    |  NULL |
    +-------+
    1 row in set (0.03 sec)
    
    +-------+
    | p_out |
    +-------+
    |     2 |
    +-------+
    1 row in set (0.03 sec)
    
    Query OK, 0 rows affected (0.03 sec)
    
    mysql> 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    总结:In传入参数,是外部将值传给存储过程来使用的,而out传出参数是为了让存储过程的执行结果回传给调用他的程序来使用的。

    mysql> select @p_out;
    +--------+
    @p_out |
    +--------+
         2 |
    +--------+
    1 row in set (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    可以看到,外部的变量已经变成的存储过程中的变量值了。

    3. Inout参数

    特点:读取外部变量,在存储过程执行完后保留新值<类似银行存款>
    INOUT类型的参数即可以接受调用者传入的参数,也可以向调用者返回数据

    传进来,又传出去。

    mysql> 
    mysql> delimiter //
    mysql> create procedure pinout(inout p_inout int)
        -> begin
        -> select p_inout;
        -> set p_inout=2;
        -> select p_inout;
        -> end;
        -> //
    Query OK, 0 rows affected (0.04 sec)
    
    mysql> delimiter ;
    mysql> set @p_inout=1
        -> ;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> call pinout(@p_inout);
    +---------+
    | p_inout |
    +---------+
    |       1 |
    +---------+
    1 row in set (0.12 sec)
    
    +---------+
    | p_inout |
    +---------+
    |       2 |
    +---------+
    1 row in set (0.12 sec)
    
    Query OK, 0 rows affected (0.14 sec)
    
    mysql> select @p_inout
        -> ;
    +----------+
    | @p_inout |
    +----------+
    |        2 |
    +----------+
    1 row in set (0.00 sec)
    
    mysql> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    4. 不加参数的情况

    如果在创建存储过程时没有指定参数类型,则需要在调用的时候指定参数值

    mysql> create table t2(id int(11)); 创建表
    mysql> delimiter //
    mysql> create procedure t2(n1 int)
        -> begin
        -> set @x=0;
        -> repeat set @x=@x+1;  作了循环
        -> insert into t2 values(@x);
        -> until @x>n1
        -> end repeat;
        -> end;
        -> //
    mysql> delimiter ;
    mysql> call t2(5); 循环5次
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    注释:

    SET @x = 0;:初始化一个变量 “@x”,将其值设置为 0。
    REPEAT:进入一个循环块,用于执行重复的操作。
    SET @x = @x + 1;:将变量 “@x” 的值增加 1。
    INSERT INTO t2 VALUES (@x);:将当前 “@x” 的值插入表 “t2” 的 “id” 列
    UNTIL @x > n1:设置循环的终止条件,如果 “@x” 的值大于 “n1”,循环结束。
    END REPEAT;:循环块的结束。
    CALL t2(5);:调用存储过程 “t2”,并传入参数值 5。这将执行存储过程的逻辑,并插入 1 到 5 的值到表 “t2” 中。

    执行结果:

    mysql> select * from t2;
    +------+
    | id   |
    +------+
    |    1 |
    |    2 |
    |    3 |
    |    4 |
    |    5 |
    |    6 |
    +------+
    6 rows in set (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    存储过程的注释

    1. 行注释

    行注释以 -- 开头,并位于一行的开头或任何有效语句的后面。行注释可以在存储过程的代码中的任何位置使用,并且只对该行有效。

    CREATE PROCEDURE my_procedure()
    BEGIN
      DECLARE my_variable INT; -- 声明一个变量
      SET my_variable = 1; -- 设置变量的值
      -- 下面是一些代码逻辑
      ...
    END;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 块注释
      块注释以 /* 开头和 */ 结尾,并可以跨越多行。块注释适用于更大的注释段落和说明。块注释可以在存储过程中的任何位置使用,并且对其包含的多行代码或注释有效。
    CREATE PROCEDURE my_procedure()
    BEGIN
      DECLARE my_variable INT;
      SET my_variable = 1;
      /*
      下面是一些代码逻辑
      可以写更多的注释内容
      ...
      */
    END;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    注释可以用于提供存储过程的名称、目的说明、参数列表、返回结果、注意事项等。编写明确和详细的注释可以提高代码的可读性和可维护性,并帮助其他人快速理解和使用存储过程。

    总结

    以上就是本节课的全部内容,欢迎评论区留言交流。

    • 💕 好啦,这就是今天要分享给大家的全部内容了,我们下期再见!
    • 💕 博客主页:mufeng.blog.csdn.net
    • 💕 本文由沐风晓月原创,首发于CSDN博客
    • 💕 每一个你想要学习的念头,都是未来的你像现在的你求救,不辜负未来,全力奔赴
  • 相关阅读:
    visummirrors seurattoscanpy dietseurat
    计算机毕业设计ssm高校会议室管理系统w169g系统+程序+源码+lw+远程部署
    JavaSE | 顺序表练习
    使用 Apache Camel 和 Quarkus 的微服务(四)
    加窗函数后频谱幅值发生了变化的修正技巧
    HTML5学习笔记(一)
    若依前端vue设置子路径
    OpenCV2 module ‘cv2‘ has no attribute ‘legacy‘
    Spring原生api操作之如何在spring配置文件添加Bean对象到Spring容器
    【LeetCode】单词规律
  • 原文地址:https://blog.csdn.net/wisdom_futrue/article/details/131446363