为了尽量的还原当时为何须要用到存储过程,下面我写了个详细的文档,咱们能够从需求文档出发来分析。html
有关存储过程以前也写了两篇文章来作铺垫。mysql
一、Mysql(7)---存储过程sql
二、Mysql(8)---游标app
一个服装类的app商城,用户会员等级分:普通会员
,vip会员
,钻石会员
。oop
如今在app上发布一款商品,但发布是能够设置该商品是 全部会员可见,仍是 指定会员可见。
如今要见3张表优化
一、商品表 二、会员表 三、商品关联会员表
这个时候,又有一个优惠券功能,一样能够设置该优惠券是 全部会员可见,仍是 指定会员可见。code
须要再建两张表htm
一、优惠券表 二、优惠券关联会员表
然而,这时候又发布一个礼品,一样能够设置该礼品是 全部会员可见,仍是 指定会员可见。blog
又须要建两张表接口
一、礼品表 二、礼品关联会员表
......
思考
: 这里面咱们发现能够优化的地方
一、每一次须要用到会员表信息的时候,都须要建一个关联表。 二、在编辑商品的时候,会员名称回显的时候,通常是两步。 1) 须要带着这个商品ID,去商品会员关联表中查询全部会员的ID 2)再拿着这些会员ID,去会员表中获取会员其它信息回显给用户。
优化
: 针对上面两点这里面咱们能够思考。
一、把N多的关联信息表,变成一张表。 二、写一个公共接口,拿着ID去查会员信息就能够,而不须要管这个ID是商品ID仍是礼品ID.....
那么这个时候问题就来了,以前的数据已经保存到相应的关联表中了,若是迁移数据首先考虑下面两个问题
问题
一、如何把以前全部的关联表数据迁移到同一张表中?
二、若是只是把全部关联表数据复制到到同一张表中,ID有没有可能重复?
针对以上,就须要存储过程来完成了,由于前期数据已经保存到不一样的关联表中了,如今须要放到同一张表中。
先建表,至于最终须要什么效果,文档也会说明
一共有5张表
说明
:key_id字段后面解释做用
/** * 一、商品表 并插入数据 */ 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');
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);
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');
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='控件关联会员表';
说明
:为何要建这张表?
上面说过了,若是都直接把全部关联会员表的数据直接复制到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
字段中。
3) 把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()$
来看运行结果:
咱们能够看到show_member
为1的数据的key_id
已经改变。
发现生成了两条纪录,并且key_id和mall_pro
中的key_id一一对应。
完美的将mall_pro_member
(商品关联会员表)中的数据迁移过来,同时mall_pro_id
也换成了key_id
。
真实环境其实比这个还复杂,不过大体思路就是这样。
完美!结束!谢幕!
只要本身变优秀了,其余的事情才会跟着好起来(少将11)