【草稿】通过Navicat创建MySQL存储过程清理指定数据库表中数据的过程记录

由于还在开发阶段,每次测试完之后需要清理数据库表,然后待清理的表数量较多,且有些基础数据表需要保留,有些表(如用户表)仅保留部分记录,由于有个发邮件的定时器,还得保证清理数据的顺序。所以尝试使用存储过程来实现一键清理数据的功能,仅以此过程分享给大家

思路:

  1. 首先是创建名为clearMaterialDatabase的函数,暂时保留一个入参isKeepMaterial来控制是否保留材料信息。
  2. 通过MySQL中自带的信息数据库INFORMATION_SCHEMA可以获取指定数据库的基本信息,包括表名、权限和数据类型等。在通过CONCAT()函数拼接指定数据库中各个表表名称,比如CONCAT('DELETE FROM',' wz_input'),结果就成了一个删除语句DELETE FROM wz_input,将这些语句组成一个结果集
  3. 通过遍历这个结果集,执行指定的SQL语句,来达到批量删除的目的。对于需要特殊处理的表,在用流程控制语句IF ELSEIF来处理,利用预处理API(EXECUTE stmt)执行相应的SQL语句

存储过程源码:

CREATE DEFINER=`root`@`localhost` PROCEDURE `clearMaterialDatabase`(IN `isKeepMaterial` VARCHAR(255))
BEGIN
  #Routine body goes here...
  #定义控制流程
  DECLARE i INT;
  
  #定义拼接的sql语句
  DECLARE strClear VARCHAR(256);
  DECLARE done INT DEFAULT 0;

  #定义游标
  DECLARE curOne CURSOR FOR SELECT CONCAT('TRUNCATE TABLE ',TABLE_NAME,';') as ClearTable 
  FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'material_wz1702';
  
  #绑定控制变量到游标,游标循环结束自动转为True
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
  
  #打开游标
  OPEN curOne;
  
  #进入循环
  FETCH curOne INTO strClear;
   repeat_label: REPEAT
        FETCH curOne INTO strClear;
        #SELECT strClear;
          
         #开始控制流程IF-ELSEIF
        #是否保留材料信息
        IF (isKeepMaterial AND ((strClear LIKE '%tc_material;')OR(strClear LIKE '%tc_material_detail;')OR(strClear LIKE '%tc_material_subject;'))) THEN
          ITERATE repeat_label;
          
        #默认保留管理员账号
        ELSEIF(strClear LIKE '%sys_user;') THEN
          SET @mysql = "DELETE from sys_user WHERE login_name not like 'admin'";
          PREPARE stmt from @mysql;
          EXECUTE stmt;
          DEALLOCATE PREPARE stmt;
          ITERATE  repeat_label;
          
        #默认保留数据字典/默认保留菜单字典/默认保留主页配置/默认保留角色信息/默认保留合同模板/最后清理邮件记录,防止清理过程中重复发送
        ELSEIF((strClear LIKE '%sys_dict;') OR (strClear LIKE '%sys_menu;') OR (strClear LIKE '%sys_config;')OR(strClear LIKE '%sys_role;')OR(strClear LIKE '%wz_contract_template')OR(strClear LIKE '%wz_bid_mail;')) THEN
          ITERATE repeat_label;
          
        #默认保留到项目层级
        ELSEIF(strClear LIKE '%sys_office;') THEN
          SET @mysql = "DELETE FROM sys_office WHERE id > ( SELECT id FROM ( SELECT id FROM sys_office  WHERE NAME = '项目级' AND del_flag = 0 ) targetId )";
          PREPARE stmt from @mysql;
          EXECUTE stmt;
          DEALLOCATE PREPARE stmt;
          ITERATE  repeat_label;
        
        #结束控制流程
        END IF;
        
        #动态执行SQL语句
        SET @mysql = strClear;
        PREPARE stmt from @mysql;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
        UNTIL done = 1 END REPEAT;
        
    #关闭游标
    CLOSE curOne;
    
    #最后清理邮件记录
     SET @mysql = "TRUNCATE TABLE wz_bid_mail;";
     PREPARE stmt from @mysql;
     EXECUTE stmt;
     DEALLOCATE PREPARE stmt;

END

过程准备:

1.MySQL预处理语句使用示例:

例一:通过文本字符拼接一个预处理语句
#创建一个函数求(X^2+Y^2)的平方根:
#?表示与参数进行绑定,?不需要用引号引用,相当于在prepare的时候就把sql写死
PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS result';
SET @X = 3;
SET @Y = 4;
EXECUTE stmt1 USING @X @Y;

输出:

result
5
例二:将文本语句当做一个变量
#创建一个函数求(X^2+Y^2)的平方根:
SET@sqlText = 'SELECT SQRT(POW(?,2)) + POW((?,2)) AS result ';
#将sqlText作为一个包含语句文本的变量放入预备语句stmt2中,表明prepare之前可以用@param变量的形式注入sql语句
PREPARE stmt2 FROM @sqlText;
SET @X = 6;
SET @Y = 8;
EXECUTE stmt2 USING @X,@Y;

输出:

result
10

注:

  • 该文本必须展现一个单一的SQL语句,而不是多个语句
  • ‘?'字符不应加引号,即使您想要把它们与字符串值结合在一起,也不要加引号。参数制作符只能被用于数据值应该出现的地方,不用于SQL关键词和标识符等
  • 参数值只能有用户变量提供,USING子句必须准确地指明用户变量。用户变量的数目与语句中的参数制造符的数量一样多。
  • 以下SQL语句可以被用在预制语句中:CREATE TABLE, DELETE, DO, INSERT, REPLACE, SELECT, SET, UPDATE和多数的SHOW语句。目前不支持其它语句。

本章参考文档:理解Mysql prepare预处理语句

2.基于Navicat 12.0创建MySQL存储过程的例子:

  • 首先进入函数向导:Navicat 12.0功能区->函数->新建函数->过程
    如何需要设置存储过程的参数,可以在这快速设置,如这里传入两个入参X和Y,类型为INT,出参R,类型为INT,所以向导如图所示:(注:这里只是提供图形化的参数设置,也可以跳过直接在存储过程中添加)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章