啊,什么,你在寫存儲(chǔ)過程?阿里巴巴開發(fā)手冊(cè)不是已經(jīng)明確說了禁用存儲(chǔ)過程了嗎?存儲(chǔ)過程難以調(diào)式、不支持對(duì)象數(shù)組這些東西,簡單邏輯需要用奇技淫巧繞一大圈才能實(shí)現(xiàn)、編寫了幾百行的存儲(chǔ)過程,誰看誰鬧心、難以適應(yīng)大量數(shù)據(jù)...當(dāng)然最主要的,我是個(gè)渣渣,不想寫這東西了?
好的,看來這位同學(xué)對(duì)存儲(chǔ)過程有偏見嘛?你看到戴金絲眼鏡的人士,就要上去打爆人家的眼鏡嗎?哈哈,首先呢,咱們呀,不是阿里巴巴,所以不用搞什么規(guī)范,不要給我扯,你就說,這個(gè)東西你能不能實(shí)現(xiàn)!調(diào)試?yán)щy,也許吧,多加幾個(gè)查詢中間變量的東西,可以半猜測(cè)半懸疑的搞定。確實(shí)不支持對(duì)象和數(shù)組,這玩意要搞成js那樣,那不得上天,這是另一種編程藝術(shù)的范疇了。對(duì)于前任遺留的東西,我從來不關(guān)心,我都繞著走,要么不服氣自己再來實(shí)現(xiàn)一遍,要么就服個(gè)軟,能用就用,能省就省,得過且過,誰跟時(shí)間過不去呢?還有,你說難以適應(yīng)大量數(shù)據(jù),我就問你,你什么時(shí)候看見了大量的數(shù)據(jù)?莫不是看到了大波浪,浮想聯(lián)翩吧,那幾個(gè)億買賣你怕是做不成啰。當(dāng)然,我是渣渣,這一點(diǎn)我完全不反駁,每個(gè)老司機(jī)都是從青蔥歲月過來的,寫著寫著就熟悉了。最后呀,不得不說,存儲(chǔ)過程有時(shí)候真的很快,車速快、穩(wěn)定性好,大車燈,配置好,就是很費(fèi)油...
咳咳,打住,這位同學(xué),雖然我不知道你在說些什么,但我聽著很奇怪的樣子。接下來,言歸正傳,今天講一講mysql里面存儲(chǔ)過程編寫的一些小細(xì)節(jié)、小坑、注意點(diǎn)之類的吧。
1、輸入、輸出參數(shù)、中間變量,這個(gè)變量名稱不要跟mysql關(guān)鍵字、要查詢或者更改的表明、字段名相同。如果有相同,它可能會(huì)出現(xiàn)既不報(bào)錯(cuò)、又不出結(jié)果的情況。
CREATE DEFINER=`root`@`%` PROCEDURE `p_xxx`(IN sys_code varchar(50))
BEGIN
-- 省略邏輯
-- 定義游標(biāo),并將sql結(jié)果集賦值到游標(biāo)中
DECLARE cur_xxx CURSOR FOR SELECT sys_code FROM t_sys_config WHERE sys_code = sys_code;
上面這樣使用,就可能出問題,避免這樣寫。一般我喜歡給所有自定義變量、參數(shù)加上下劃線后綴,這樣一眼就能看出哪些是我自己定義的變量。
2、變量要先定義后使用、游標(biāo)先定義后使用、各種HANDLER定義在游標(biāo)之后。
3、如何判斷游標(biāo)結(jié)束?使用HANDLER
-- cur_XXX是否結(jié)束的變量
DECLARE finish int DEFAULT 0;
-- 定義游標(biāo),并將sql結(jié)果集賦值到游標(biāo)中
DECLARE cur_xxx CURSOR FOR SELECT xxx_SQL;
-- 聲明當(dāng)游標(biāo)遍歷完后將標(biāo)志變量置成某個(gè)值
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finish = 1;
在while循環(huán)中,判斷finish變量是否等于1,如果等于了,則游標(biāo)遍歷完畢了。
4、存儲(chǔ)過程沒有try catch語句,如果在一個(gè)循環(huán)中有很多次sql執(zhí)行,只要一次不成功,我就要回滾修改,該如何實(shí)現(xiàn)?
-- 定義sql語句執(zhí)行是否正確的變量
DECLARE sql_error_ INTEGER DEFAULT 0;
-- sql語句執(zhí)行錯(cuò)誤 設(shè)置值
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET sql_error_ = 1;
在循環(huán)中,如果有sql執(zhí)行錯(cuò)誤,則sql_seeor_=1,在循環(huán)中一旦判定該值等于1,結(jié)束循環(huán)。結(jié)束后,sql執(zhí)行有錯(cuò)誤,那么回滾就可以了。
5、游標(biāo)查詢字段和賦值字段,名稱要不一致,如果一樣,就會(huì)出問題,比如你查詢sys_code字段值,賦值給sys_code變量,那就會(huì)出問題。
-- 定義游標(biāo),并將sql結(jié)果集賦值到游標(biāo)中
DECLARE cur_xxx CURSOR FOR SELECT sys_code,sys_name FROM t_sys_config;
-- 打開游標(biāo)
OPEN cur_need_convert;
-- 將游標(biāo)中的值賦值給變量,注意:變量名不要和返回的列名同名,變量順序要和sql結(jié)果列的順序一致
FETCH cur_xxx INTO sys_code_,sys_name_;
6、CONCAT函數(shù),如果里面參數(shù)有null值的,則最后結(jié)果為null,因此一定要注意對(duì)null值的處理,要不然,可能得不到你想要的執(zhí)行效果。
7、如何判斷以逗號(hào)分隔的字符串,分隔后幾個(gè)對(duì)象,如 123,456,789 ,逗號(hào)分隔開以后,有3個(gè)對(duì)象。
(case when length(xxx) = 0 THEN 0 ELSE (length(xxx) - LENGTH(REPLACE(xxx,',','')) + 1) END) AS count_
原理就是計(jì)算整個(gè)字符串的長度,以及將這個(gè)字符串中的逗號(hào)去除以后的長度,兩個(gè)長度相減即可得到。
8、上面計(jì)算出了對(duì)象個(gè)數(shù),現(xiàn)在要求把這些對(duì)象一個(gè)一個(gè)的分割開來,做其余邏輯操作 如果 123,456,789 分割開來得到 123 456 789 。這個(gè)要用到循環(huán),去處理。
SET deal_count_ = 0;
WHILE deal_count_ < count_ DO
-- 截取出單個(gè)
SET single_s = SUBSTRING_INDEX(xxx,',',1);
-- 將已經(jīng)截取出來的從原字符串中給剔除掉
SET xxx = REPLACE(xxx,CONCAT(IFNULL(xxx,''),','),'');
-- 已經(jīng)處理數(shù)+1
SET deal_count_ = count_ + 1;
-- 其余邏輯
END WHILE;
好了,今天就說這么多,你們學(xué)會(huì)了多少呢?