当前位置: 首页 > news >正文

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

场景

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

创建有参存储过程

CREATE DEFINER=`root`@`%` PROCEDURE `auto_create_month_table`(
	IN `database_name` VARCHAR(50),
	IN `table_name` VARCHAR(50)
)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT '每月自动生成表一张表'
BEGIN
	-- 声明变量
	DECLARE old_table_name VARCHAR(128);
	DECLARE new_table_name VARCHAR(128);
	DECLARE done INT DEFAULT 0;
	
	-- 声明游标
	DECLARE table_cursor CURSOR FOR SELECT TABLE_NAME FROM `information_schema`.`TABLES` WHERE TABLE_SCHEMA = database_name AND TABLE_NAME = table_name;
	-- 如果没有数据返回或者 select 出现异常,程序继续,并将变量 done 设为 1
	DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; 
	
	-- 打开游标
	OPEN table_cursor;   
	-- 遍历游标
	REPEAT
		--  获取当前游标指针记录,使用 fetch 来取出数据,取出值赋给自定义的变量
		FETCH table_cursor INTO old_table_name;
		IF NOT done THEN 
			-- 真正要操作的需求
			SELECT concat(table_name,'_',DATE_FORMAT(DATE_ADD(CURDATE(),INTERVAL 1 MONTH), '%Y%m')) INTO new_table_name;
			
			SET @sql_cmd = CONCAT('create table if not exists `',new_table_name,'` like `' , old_table_name,'`');
			-- 如果需要变量返回,使用 select,如:select 变量名
			-- SELECT  @sql_cmd;
			
			-- 预定义一个语句,并将它赋给 pre_stmt
			PREPARE pre_stmt FROM @sql_cmd; 
			-- 执行语句,存储过程如果有参数,后面加参数格式为:@参数名=value,也可直接为参数值value,如果 pre_stmt 不存在,将会引发一个错误
			EXECUTE pre_stmt;
			-- 释放一个预定义语句的资源
			DEALLOCATE PREPARE pre_stmt;
		END IF ;
	-- 根据 done 判断是否结束
	UNTIL done END REPEAT;
	-- 关闭游标
	CLOSE table_cursor;
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 参数的默认值。如果定义了默认值,不必指定该参数的值即可执行过程。


变量赋值

set {变量名=表达式}
-- 或
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的调用
  • 存储过程是预编译过的,执行效率高
  • 存储过程的代码直接存放于数据库中,通过存储过程名直接调用,减少网络通讯,节省开销;
  • 可提高数据库的安全性和数据的完整性
  • 存储过程可以重复使用,减少数据库开发人员的工作量


缺点:

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

相关文章:

  • 我们这样的人
  • < Linux > 进程概念(2)
  • Qt5开发从入门到精通——第四篇十二节(不规则窗体)
  • MySQL 5.7.x--命令行自带帮助文档的使用,超级棒!!!
  • 手撕前端面试题【javascript】
  • Qt5开发从入门到精通——第四篇十三节(程序启动画面 )
  • postman+Newman+jenkins实现接口自动化测试持续集成
  • 阿里达摩院(研究型实习生)
  • 汽车电子常用外围硬件电路设计
  • 猿创征文|半导体二极管
  • 《机器学习实战》学习笔记(十一)
  • 多态原理之虚函数表VBTL
  • 域前期信息收集
  • C语言经典算法实例3:数组元素排序
  • 网络安全工具AntSword蚁剑内存马使用
  • 时间复杂度分析经典问题——最大子序列和
  • 2019.2.20 c++ 知识梳理
  • ECS应用管理最佳实践
  • express.js的介绍及使用
  • Hexo+码云+git快速搭建免费的静态Blog
  • IP路由与转发
  • React Native移动开发实战-3-实现页面间的数据传递
  • React-redux的原理以及使用
  • springboot_database项目介绍
  • 通过npm或yarn自动生成vue组件
  • 一、python与pycharm的安装
  • 终端用户监控:真实用户监控还是模拟监控?
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ​人工智能之父图灵诞辰纪念日,一起来看最受读者欢迎的AI技术好书
  • (12)目标检测_SSD基于pytorch搭建代码
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (Redis使用系列) Springboot 在redis中使用BloomFilter布隆过滤器机制 六
  • (办公)springboot配置aop处理请求.
  • (附源码)node.js知识分享网站 毕业设计 202038
  • (力扣题库)跳跃游戏II(c++)
  • (十六)串口UART
  • (一)基于IDEA的JAVA基础1
  • (转)【Hibernate总结系列】使用举例
  • (转)3D模板阴影原理
  • (转)scrum常见工具列表
  • (转)拼包函数及网络封包的异常处理(含代码)
  • .dwp和.webpart的区别
  • .NET BackgroundWorker
  • .Net MVC4 上传大文件,并保存表单
  • .NET NPOI导出Excel详解
  • .net 怎么循环得到数组里的值_关于js数组
  • .NET/C# 异常处理:写一个空的 try 块代码,而把重要代码写到 finally 中(Constrained Execution Regions)
  • .NET版Word处理控件Aspose.words功能演示:在ASP.NET MVC中创建MS Word编辑器
  • .Net多线程总结
  • .pop ----remove 删除
  • .skip() 和 .only() 的使用
  • .vollhavhelp-V-XXXXXXXX勒索病毒的最新威胁:如何恢复您的数据?
  • [ CTF ] WriteUp-2022年春秋杯网络安全联赛-冬季赛
  • [AutoSar NVM] 存储架构
  • [Excel] vlookup函数