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

相关推荐
松涛和鸣1 小时前
72、IMX6ULL驱动实战:设备树(DTS/DTB)+ GPIO子系统+Platform总线
linux·服务器·arm开发·数据库·单片机
likangbinlxa1 小时前
【Oracle11g SQL详解】UPDATE 和 DELETE 操作的正确使用
数据库·sql
r i c k2 小时前
数据库系统学习笔记
数据库·笔记·学习
野犬寒鸦2 小时前
从零起步学习JVM || 第一章:类加载器与双亲委派机制模型详解
java·jvm·数据库·后端·学习
IvorySQL3 小时前
PostgreSQL 分区表的 ALTER TABLE 语句执行机制解析
数据库·postgresql·开源
·云扬·3 小时前
MySQL 8.0 Redo Log 归档与禁用实战指南
android·数据库·mysql
IT邦德3 小时前
Oracle 26ai DataGuard 搭建(RAC到单机)
数据库·oracle
惊讶的猫3 小时前
redis分片集群
数据库·redis·缓存·分片集群·海量数据存储·高并发写
不爱缺氧i4 小时前
完全卸载MariaDB
数据库·mariadb
纤纡.4 小时前
Linux中SQL 从基础到进阶:五大分类详解与表结构操作(ALTER/DROP)全攻略
linux·数据库·sql