MySQL(9)---纪录一次实际开发过程中用到的复杂存储过程
Mysql(9)---纪录一次实际开发过程中用到的复杂存储过程
为了尽可能的还原当时为什么需要用到存储过程,下面我写了个详细的文档,我们可以从需求文档出发来分析。
有关存储过程之前也写了两篇文章来做铺垫。
一、需求背景
一个服装类的app商城,用户会员等级分:普通会员
,vip会员
,钻石会员
。
现在在app上发布一款商品,但发布是可以设置该商品是 所有会员可见,还是 指定会员可见。
现在要见3张表
1、商品表
2、会员表
3、商品关联会员表
这个时候,又有一个优惠券功能,同样可以设置该优惠券是 所有会员可见,还是 指定会员可见。
需要再建两张表
1、优惠券表
2、优惠券关联会员表
然而,这时候又发布一个礼品,同样可以设置该礼品是 所有会员可见,还是 指定会员可见。
又需要建两张表
1、礼品表
2、礼品关联会员表
......
思考
: 这里面我们发现可以优化的地方
1、每一次需要用到会员表信息的时候,都需要建一个关联表。
2、在编辑商品的时候,会员名称回显的时候,一般是两步。
1) 需要带着这个商品ID,去商品会员关联表中查询所有会员的ID
2)再拿着这些会员ID,去会员表中获取会员其它信息回显给用户。
优化
: 针对上面两点这里面我们可以思考。
1、把N多的关联信息表,变成一张表。
2、写一个公共接口,拿着ID去查会员信息就可以,而不需要管这个ID是商品ID还是礼品ID.....
那么这个时候问题就来了,之前的数据已经保存到相应的关联表中了,如果迁移数据首先考虑下面两个问题
问题
1、如何把之前所有的关联表数据迁移到同一张表中?
2、如果只是把所有关联表数据复制到到同一张表中,ID有没有可能重复?
针对以上,就需要存储过程来完成了,因为前期数据已经保存到不同的关联表中了,现在需要放到同一张表中。
二、表建立
先建表,至于最终需要什么效果,文档也会说明
一共有5张表
1、商品表
说明
:key_id字段后面解释作用
/**
* 1、商品表 并插入数据
*/
CREATE TABLE `mall_pro` (
`mall_id` char(32) NOT NULL,
`pro_name` varchar(32) DEFAULT NULL COMMENT '显示名称',
`cash_cost` double(10,1) DEFAULT '0.0' COMMENT '商品价格',
`show_member` int(1) DEFAULT '0' COMMENT '显示 0所有会员 1指定会员',
`status` int(1) DEFAULT '1' COMMENT '状态:1正常 0删除',
`key_id` varchar(32) DEFAULT '0' COMMENT '会员控件表key',
PRIMARY KEY (`mall_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品表';
INSERT INTO `mall_pro` (`mall_id`, `pro_name`, `cash_cost`, `show_member`, `status`, `key_id`)
VALUES
('1','手表',100.0,0,1,'0'),
('2','手机',888.0,1,1,'0'),
('3','电脑',3888.0,1,1,'0');
2、会员表
CREATE TABLE `member` (
`member_id` char(32) NOT NULL,
`member_grade` varchar(32) DEFAULT NULL COMMENT '会员等级',
`status` int(1) DEFAULT '1' COMMENT '状态:1正常 0删除',
PRIMARY KEY (`member_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='会员表';
INSERT INTO `member` (`member_id`, `member_grade`, `status`)
VALUES
('1','普通会员',1),
('2','银卡会员',1),
('3','金卡会员',1);
3、商品关联会员表
CREATE TABLE `mall_pro_member` (
`id` char(32) NOT NULL,
`mall_id` varchar(32) DEFAULT NULL COMMENT '商品ID',
`member_id` varchar(32) DEFAULT NULL COMMENT '会员ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品关联会员表';
INSERT INTO `mall_pro_member` (`id`, `mall_id`, `member_id`)
VALUES
('1','2','1'),
('2','2','2'),
('3','3','2');
4、新建统一管理关联会员的表
CREATE TABLE `member_widget_relation` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`key_id` varchar(32) NOT NULL DEFAULT '' COMMENT 'KeyID',
`member_id` varchar(32) NOT NULL DEFAULT '' COMMENT '会员表ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='控件关联会员表';
5、会员控件表key
说明
:为什么要建这张表?
上面说过了,如果都直接把所有关联会员表的数据直接复制到member_widget_relation
有可能会ID重复的可能。具体步骤下面会说。
CREATE TABLE `member_widget` (
`key_id` varchar(32) NOT NULL DEFAULT '',
PRIMARY KEY (`key_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
需求步骤
1)生成一个随机UUID,当member_widget(会员控件表key)
的主键。
2)生成纪录的同时把这个UUID,放到mall_pro(商品表)
的key_id
字段中。
- 把
mall_pro_member(商品关联会员表)
数据迁移到member_widget_relation(新建统一管理关联会员的表)
中,只不过把关联的mall_id
换成key_id
。
4)下次取该商品的会员信息,只要拿着这个key_id
到member_widget_relation
取就可以了。
三、存储过程实践
下面我直接把我写好的存储过程贴出来。
drop PROCEDURE if exists member_process; #在没有重新申明结束标志之前 都是以 ; 结束。
DELIMITER $ # 申明结束标志
CREATE PROCEDURE member_process ()
BEGIN
# 创建接收游标数据的变量
DECLARE keyId varchar(32);
DECLARE mallId varchar(32);
# 创建结束标志变量
DECLARE done int DEFAULT false;
#创建游标 获取mall_id和key_id的集合
DECLARE coup_cur CURSOR FOR
SELECT mall_id, key_id
FROM mall_pro
WHERE show_member = 1 AND status = 1;
# 指定游标循环结束时的返回值
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = true;
# 打开游标
OPEN coup_cur;
# 开始循环游标里的数据
loop_a: LOOP
# 根据游标当前指向的一条数据 插入到上面申明的局部变量中
FETCH coup_cur INTO mallId, keyId;
IF done THEN
LEAVE loop_a;
END IF;
# 为什么是0 因为keyId为后面新增字段所以之前的老数据默认都为0,只有新数据key_id才不为0
IF keyId = 0 THEN
# 开启事物 先把数据保存后提交事物
START TRANSACTION;
# 生成随机UUID
SET keyId = REPLACE(UUID(), '-', '');
# 插入member_widget表中
INSERT INTO member_widget (key_id) VALUES (keyId);
# 同时把keyId更新到mall_pro表中
UPDATE mall_pro SET key_id = keyId WHERE mall_id = mallId;
COMMIT;
# 接下来的BEGIN 所做的事情就是把mall_pro_member数据的迁移到member_widget_relation中
BEGIN
DECLARE memberId varchar(32);
DECLARE done1 int DEFAULT false;
# 取出mall_pro_member表中的关联数据
DECLARE coup_cur1 CURSOR FOR
SELECT member_id FROM mall_pro_member WHERE mall_id = mallId;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done1 = true;
OPEN coup_cur1;
loop_b: LOOP
FETCH coup_cur1 INTO memberId;
IF done1 THEN
LEAVE loop_b;
END IF;
# 插入到member_widget_relation表中
INSERT INTO member_widget_relation (key_id, member_id) VALUES (keyId, memberId);
END LOOP loop_b;
END;
END IF;
END LOOP loop_a;
END$
# 运行存储过程
call member_process()$
来看运行结果:
1、mall_pro(商品表)
我们可以看到show_member
为1的数据的key_id
已经改变。
2、member_widget会员控件表key)
发现生成了两条纪录,而且key_id和mall_pro
中的key_id一一对应。
3、member_widget_relation(新建统一管理关联会员的表)
完美的将mall_pro_member
(商品关联会员表)中的数据迁移过来,同时mall_pro_id
也换成了key_id
。
真实环境其实比这个还复杂,不过大致思路就是这样。
完美!结束!谢幕!
只要自己变优秀了,其他的事情才会跟着好起来(少将11)
MySQL(9)---纪录一次实际开发过程中用到的复杂存储过程的更多相关文章
- linux安装mysql全纪录[包括yum和rpm安装,编码,远程连接以及大小写问题]
linux安装mysql全纪录[包括yum和rpm安装,编码,远程连接以及大小写问题] 一.查看mysql是否已经安装 使用“whereis mysql”命令来查看mysql安装路径: [root@h ...
- [MySQL数据库之Navicat.pymysql模块、视图、触发器、存储过程、函数、流程控制]
[MySQL数据库之Navicat.pymysql模块.视图.触发器.存储过程.函数.流程控制] Navicat Navicat是一套快速.可靠并价格相当便宜的数据库管理工具,专为简化数据库的管理及降 ...
- mysql 复杂的查询语句,工作中用到的记录下
1 去重查询 select distinct id from user_info where xxxxxx 2 group by 分组查询中排序 group by本身没有排序功能,这可能是mysql ...
- [ 转载 ] Centos安装Mysql数据库纪录
yum install mysql-community-server依赖关系错误 https://www.cnblogs.com/lzj0218/p/5724446.html rpm -qa|grep ...
- php开发过程中用什么方法来加快页面的加载速度
1,数据库优化;2,php缓存;3,使用zend引擎(其它框架);4,分布式部署;5,静态
- 「mysql优化专题」90%程序员没听过的存储过程和存储函数教学(7)
一.MYSQL储存过程简介(技术文): 储存过程是一个可编程的函数,它在数据库中创建并保存.它可以有SQL语句和一些特殊的控制结构组成.当希望在不同的应用程序或平台上执行相同的函数,或者封装特定功能时 ...
- MySQL 第七篇:视图、触发器、事务、存储过程、函数
一 视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,可以将该结果集当做表来使用. 使用视图我们可以把查询过程中的 ...
- 【C#】【MySQL】C# 查询数据库语句@Row:=@Row+1以及执行存储过程失败解决方案
如何实现数据库查询产生虚拟的一列序号的功能: ) )AS r; 该语句可以实现产生虚拟的一列数据在MySQL中运行没有问题. 但是在C#里面调用去出现了错误"Parameter '@ROW' ...
- 转!mysql 命令行下 通过DELIMITER临时改变语句分隔符 执行存储过程
mysql 在 Navicat 界面工具 执行存储过程ok,但是在命令行下执行失败. 原因在于,默认的MySQL语句分隔符为' ; ',在输入' ; '的时候,“以为”语句已经结束了,但实际上语句还没 ...
随机推荐
- CSAPP lab1——位运算
本次为一次计算机系统实验,就是使用一些基本的运算符来实现函数功能. ps做这些题让我想起大一上学期刚学二进制时被鹏哥支配的痛苦. 知识准备: 1.负数等于正数取反加一. 2.左移一位相当于将这个数扩大 ...
- ASP.NET Core - 基于IHttpContextAccessor实现系统级别身份标识
问题引入: 通过[ASP.NET Core[源码分析篇] - 认证]这篇文章中,我们知道当请求通过认证模块时,会给当前的HttpContext赋予当前用户身份标识,我们在需要授权的控制器中打上[Aut ...
- Mybatis+Spring框架整合
1.整合思路 1.SqlSessionFactory对象应该放到spring容器中作为单例存在. 2.传统dao的开发方式中,应该从spring容器中获得sqlsession对象. 3.Mapper代 ...
- Java入门——在Linux环境下安装JDK并配置环境变量
Java入门——在Linux环境下安装JDK并配置环境变量 摘要:本文主要说明在Linux环境下JDK的安装,以及安装完成之后环境变量的配置. 使用已下载的压缩包进行安装 下载并解压 在Java的官网 ...
- 【koa2】用户注册、登录校验与加盐加密
加密与解密 先介绍一下关于服务端用户名跟密码的存储状态,我们知道当前端在注册一个新用户时,会在表单内填入用户名和密码,并通过post请求提交到服务器,服务器再把用户名和密码从ctx.request.b ...
- Dynamics 365 CE Update消息PostOperation阶段Image的尝试
我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...
- Xcode更新到10.0之后遇到的那些坑:
1.之前不在一个文件里的图片可以重新,更新之后图片不能重名了. 2.之前的双击.h.m文件不能重新开出个界面了 3. 4. ...... 未完待续
- opencv-python 图像处理(五)
Canny边缘检测 1) 使用高斯滤波器,以平滑图像,滤除噪声. 2) 计算图像中每个像素点的梯度强度和方向. 3) 应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测 ...
- curl的使用指南
一.查看网页源码 直接在curl命令后加上网址,就可以看到网页源码.我们以网址www.sina.com为例(选择该网址,主要因为它的网页代码较短): $ curl www.sina.com M ...
- Html table 内容超出显示省略号
内容超出显示省略号: <html> <style> table { table-layout: fixed; width: 100%; } table, th, td { bo ...