MySQL新学知识(二)MySQL存储过程

MySQL新学知识(二)


前言

👨‍💻👨‍🌾📝记录学习成果,以便温故而知新

本专题把一阶段学到知识MySQL做一个总结


一、mysql客户端建立存储过程

MySQL文档https://dev.mysql.com/doc/refman/8.0/en/stored-programs-defining.html中一个例子虽然简单,但是很有代表性。

例子如下:

mysql> delimiter //

mysql> CREATE PROCEDURE dorepeat(p1 INT)

-> BEGIN

-> SET @x = 0;

-> REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;

-> END

-> //

Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;

mysql> CALL dorepeat(1000);

Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @x;

±-----+

| @x |

±-----+

| 1001 |

±-----+

1 row in set (0.00 sec)

客户端效果截图如下:

其中delimiter //是重新定义分隔符,默认分隔符是";"。因为存储过程体里语句的分隔符是";",而存储过程体的分隔符也是";",这样会有冲突,所以需要重新定义,这样存储过程体里语句使用";"作为分隔符就不会与存储过程体的分隔符"//"冲突了。

这个例子还演示了REPEAT循环与存储过程调用。

二、工具中建立存储过程

编辑已经建立的存储过程,与客户端的区别就是不要重新定义分隔符,省去了麻烦,如下图:

三、几个常用存储过程的例子

刚开始学Java的时候有种思路是所有的数据库操作都是用代码来实现以保证程序逻辑的可移植,防止换数据库还需要修改存储过程,所以对于存储过程的学习是浅尝辄止。后来发现有时存储过程还是很管用的,记录如下:

1.执行单语句

下面以新增用户权限为例

sql 复制代码
CREATE DEFINER=`root`@`%` PROCEDURE `SP_ADD_PRIVILEGES`(IN `moduleName` varchar(100))
BEGIN
    -- 模块名称
    -- 如call SP_ADD_PRIVILEGES('模块名称');
    SET @grant_privileges = CONCAT('INSERT INTO t_privileges(user_id, module_name)
    SELECT user_id, \'', moduleName, '\' 
    FROM t_user
    WHERE role_name != \'Admin\' AND user_id NOT IN (SELECT user_id FROM t_privileges WHERE module_name = \'', moduleName, '\')');
    
    PREPARE stmt FROM @grant_privileges;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END

用户表内容如图:

调用存储过程如下:

sql 复制代码
CALL SP_ADD_PRIVILEGES('新增用户');

调用结果:

调用后t_privileges表内容:

这个存储过程的要点在于拼接语句。

2.循环执行语句

下面以给T开头的用户赋单表权限为例

sql 复制代码
CREATE DEFINER=`root`@`%` PROCEDURE `SP_GRANTTABLE`(IN `tableName` varchar(100))
BEGIN
    -- 根据表名设置权限
    -- 如call SP_GRANTTABLE('test.t_privileges');
    DECLARE has_next boolean DEFAULT TRUE;
    DECLARE num int DEFAULT 0;
    DECLARE sqlStmt varchar(5000);
    DECLARE sqlResult CURSOR FOR SELECT CONCAT('GRANT Select ON TABLE ', tableName, ' TO `', User, '`@`%`;') FROM mysql.user WHERE User LIKE 'T%';
    DECLARE CONTINUE HANDLER FOR not found SET has_next = FALSE;
    
    OPEN sqlResult;
    EXIT_LOOP: LOOP
        FETCH sqlResult INTO sqlStmt;
        IF !has_next THEN
            LEAVE EXIT_LOOP;
        END IF;
        
        SET @grant_privileges = sqlStmt;
        PREPARE stmt FROM @grant_privileges;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
        SET num = num + 1;
    END LOOP;
    CLOSE sqlResult;
    
    SELECT CONCAT('共授权', num, '位用户') AS '返回信息';
END

如下图红框新建两个用户:

调用存储过程如下:

sql 复制代码
CALL SP_GRANTTABLE('test.t_privileges');

调用结果如下:

这个存储过程要点:

  1. 定义游标CURSOR;
  2. 为"not found"定义"CONTINUE HANDLER",作用是推出异常;
  3. 最后一个查询语句用户调用结果返回

2个列子介绍一些有用知识点,以后要是学到新的再逐步补充到这篇。

相关推荐
科兽的AI小记4 小时前
从Coze到BuildingAI:一个程序员对开源AI应用平台的实战体验
数据库·开源·创业
Boop_wu5 小时前
[MySQL] 数据库设计
java·数据库·oracle
xiaoye37086 小时前
达梦数据库连接配置yaml 文件配置
服务器·数据库·oracle
TDengine (老段)7 小时前
TDengine 数学函数 PI 用户手册
大数据·数据库·时序数据库·iot·tdengine·涛思数据
aristo_boyunv7 小时前
Redis发布订阅【充当消息中间件】
数据库·redis·缓存
zz-zjx8 小时前
MySQL 开源主从复制实战指南(SRE 可靠性优先版)
数据库·mysql·开源
计算机学姐11 小时前
基于微信小程序的高校班务管理系统【2026最新】
java·vue.js·spring boot·mysql·微信小程序·小程序·mybatis
Microsoft Word15 小时前
向量数据库与RAG
数据库·人工智能·向量数据库·rag
位步15 小时前
在linux系统中使用通用包安装 Mysql
android·linux·mysql