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个列子介绍一些有用知识点,以后要是学到新的再逐步补充到这篇。

相关推荐
+VX:Fegn08954 小时前
计算机毕业设计|基于springboot + vue蛋糕店管理系统(源码+数据库+文档)
前端·数据库·vue.js·spring boot·课程设计
哈__6 小时前
KES-Operator重塑Kubernetes环境下的KES数据库集群管理
数据库·kubernetes·operator·kes
IvorySQL7 小时前
IvorySQL 5.6 发布:PG 18.6 内核升级,沙盒即开即用
数据库·人工智能·postgresql
CNSSIRD数据库8 小时前
中国企业环境信用数据库2003-2026
大数据·数据库·数据分析·论文笔记
fd32009 小时前
达梦数据库更新统计信息后仍走旧执行计划解决方案
数据库
百万蹄蹄向前冲9 小时前
密码都对Node.js却连不上Linux数据库
linux·mysql
华章酱9 小时前
MySQL幻读是怎么出现的
数据库·mysql·幻读
浅念-9 小时前
Redis基础详解:单线程模型、String与Hash数据结构
服务器·数据库·redis·sql·mysql·nosql数据库·nosql
updayday85410 小时前
离职域账号状态变更与Ping64操作记录核对
大数据·网络·数据库·安全·智能路由器