爲了儘量的還原當時爲何須要用到存儲過程,下面我寫了個詳細的文檔,咱們能夠從需求文檔出發來分析。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)