• MySQL 存储过程创建指定表结构


    场景

    由于存储数据量太大,当一个表超过 1000w 的数据时 MySQL 性能会逐渐下降,对数据操作时非常耗时,为了优化数据库性能,使用了分表的方式每个月对数据实现水平分割,也就是说每月自动生成表一张表。

    创建有参存储过程

    1. CREATE DEFINER=`root`@`%` PROCEDURE `auto_create_month_table`(
    2. IN `database_name` VARCHAR(50),
    3. IN `table_name` VARCHAR(50)
    4. )
    5. LANGUAGE SQL
    6. NOT DETERMINISTIC
    7. CONTAINS SQL
    8. SQL SECURITY DEFINER
    9. COMMENT '每月自动生成表一张表'
    10. BEGIN
    11. -- 声明变量
    12. DECLARE old_table_name VARCHAR(128);
    13. DECLARE new_table_name VARCHAR(128);
    14. DECLARE done INT DEFAULT 0;
    15. -- 声明游标
    16. DECLARE table_cursor CURSOR FOR SELECT TABLE_NAME FROM `information_schema`.`TABLES` WHERE TABLE_SCHEMA = database_name AND TABLE_NAME = table_name;
    17. -- 如果没有数据返回或者 select 出现异常,程序继续,并将变量 done 设为 1
    18. DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
    19. -- 打开游标
    20. OPEN table_cursor;
    21. -- 遍历游标
    22. REPEAT
    23. -- 获取当前游标指针记录,使用 fetch 来取出数据,取出值赋给自定义的变量
    24. FETCH table_cursor INTO old_table_name;
    25. IF NOT done THEN
    26. -- 真正要操作的需求
    27. SELECT concat(table_name,'_',DATE_FORMAT(DATE_ADD(CURDATE(),INTERVAL 1 MONTH), '%Y%m')) INTO new_table_name;
    28. SET @sql_cmd = CONCAT('create table if not exists `',new_table_name,'` like `' , old_table_name,'`');
    29. -- 如果需要变量返回,使用 select,如:select 变量名
    30. -- SELECT @sql_cmd;
    31. -- 预定义一个语句,并将它赋给 pre_stmt
    32. PREPARE pre_stmt FROM @sql_cmd;
    33. -- 执行语句,存储过程如果有参数,后面加参数格式为:@参数名=value,也可直接为参数值value,如果 pre_stmt 不存在,将会引发一个错误
    34. EXECUTE pre_stmt;
    35. -- 释放一个预定义语句的资源
    36. DEALLOCATE PREPARE pre_stmt;
    37. END IF ;
    38. -- 根据 done 判断是否结束
    39. UNTIL done END REPEAT;
    40. -- 关闭游标
    41. CLOSE table_cursor;
    42. END

    存储过程名称为 auto_create_month_table,参数分别为:database_name,table_name。

    调用存储过程

    CALL `auto_create_month_table`('test', 'temp_bigint');

    注意

    执行存储过程时出现一下异常

    the user specified as a definer ('root'@'%') does not exist

    此问题是权限问题,操作存储过程的用户不存在,授权权限即可。

    添加 root 权限

    grant all privileges on *.* to root@"%" identified by ".";

    刷新权限

    flush privileges;


    声明变量

    declare {变量} {数据类型}

    声明变量使用 declare 命令,变量必须先声明后使用。变量是有作用域的,作用范围在 begin 与end 中使用。

    default 参数的默认值。如果定义了默认值,不必指定该参数的值即可执行过程。


    变量赋值

    1. set {变量名=表达式}
    2. -- 或
    3. sel select{变量名=表达式}

    declare 和 set 区别

    • declare 的变量和参数传入的变量则必须用 concat 来连接
    • set var=value 这样定义的变量直接写在字符串中就会被当作变量转换
    • declare 时用来声明变量,变量默认赋值使用的 default;改变变量值需要使用 set 变量=值;

    游标

    游标是一个存储在MySQL服务器上的数据库查询,它不是一条 selec t语句,而是被该语句所检索出来的结果集。

    定义游标

    DECLARE table_cursor CURSOR FOR SELECT TABLE_NAME FROM `information_schema`.`TABLES` WHERE TABLE_SCHEMA = database_name AND TABLE_NAME = table_name;

    查询 `information_schema`.`TABLES` 表的 table_name 作为游标.

    存储过程异常处理

    有时候,不希望存储过程抛出错误中止执行,而是希望返回一个错误码。 可以通过定义 continue/exit 异常处理的 handler 来捕获 sqlwarning/not found/sqlexception (警告/无数据/其他异常)。

    for 后面可以改为 sqlwarning, not found, sqlexception 来指示所有异常都处理,当不进行异常处理时,以下代码将直接抛出一个 error 1062 (23000) 。

    例:

    declare continue handler for sqlstate '02000' set done = 1;

    定义 continue/exit 异常处理的 handler 来捕获 sqlstate,避免抛出错误,定义一个返回参数 done 赋予特殊值来表示失败,可以通过获取返回值而不是捕获异常的方式来处理业务逻辑。

    '02000' 代表发生下述异常之一:

    • SELECT INTO 语句或 INSERT 语句的子查询的结果为空表
    • 在搜索的 UPDATE 或 DELETE 语句内标识的行数为零
    • 在 FETCH 语句中引用的游标位置处于结果表最后一行之后

    当 fetch 游标到了数据库表格最后一行的时候,设置 done=1。

    返回值

    变量需要返回,可以使用select语音,如:select 变量名


    存储过程的优缺点

    优点:

    • 将重复性很高的一些操作,封装到一个存储过程中,简化了对这些SQL的调用
    • 存储过程是预编译过的,执行效率高
    • 存储过程的代码直接存放于数据库中,通过存储过程名直接调用,减少网络通讯,节省开销;
    • 可提高数据库的安全性和数据的完整性
    • 存储过程可以重复使用,减少数据库开发人员的工作量


    缺点:

    • 如果使用大量存储过程,会使这些存储过程的每个连接的内存大大增加
    • 存储过程的构造不是为开发复杂和灵活的业务逻辑而设计的
    • 调试存储过程很困难
    • 开发和维护存储过程并不容易
    • 可移植性差

  • 相关阅读:
    文字的选择与排版
    【JavaEE进阶系列 | 从小白到工程师】Calendar类的常用方法使用与创建对象
    【Day-30慢就是快】代码随想录-二叉树-找树左下角的值
    C/C++内存管理
    jsoup使用指南
    Microsemi Libero SoC 教程1 (Libero开发环境)
    LVS负载均衡群集--NAT
    基于安卓大学生兼职APP设计与实现
    【机器学习】详解回归(Regression)
    Linux嵌入式串口UART测试程序
  • 原文地址:https://blog.csdn.net/xhaimail/article/details/126618968