例子
-- 秒殺執(zhí)行存儲過程 DELIMITER $$ -- 將分隔符; 轉(zhuǎn)換為 $$ -- 定義存儲過程 -- 參數(shù): in 輸入?yún)?shù); out 輸出參數(shù) -- row_count():返回上一條修改類型sql(delete,insert,update)的影響行數(shù) -- row_count: 0:未修改數(shù)據(jù); >0:表示修改的行數(shù); <0:sql錯誤/未執(zhí)行修改sql CREATE PROCEDURE `seckill`.`execute_seckill` (in v_seckill_id bigint,in v_phone bigint, in v_kill_time timestamp,out r_result int)--創(chuàng)建儲存過程 BEGIN-- 開始執(zhí)行 DECLARE insert_count int DEFAULT 0;-- 定義變量 START TRANSACTION;--開啟事物管理 insert ignore into success_killed (seckill_id,user_phone,create_time) values (v_seckill_id,v_phone,v_kill_time);--執(zhí)行insert語句 select row_count() into insert_count;--返回影響行數(shù) IF (insert_count = 0) THEN ROLLBACK;--事務回滾 set r_result = -1;--返回未修改數(shù)據(jù) ELSEIF(insert_count < 0) THEN ROLLBACK;--事務回滾 set R_RESULT = -2;--返回未知錯誤 ELSE update seckill set number = number-1 where seckill_id = v_seckill_id and end_time > v_kill_time and start_time < v_kill_time and number > 0;--執(zhí)行update語句 select row_count() into insert_count;--返回影響行數(shù) IF (insert_count = 0) THEN ROLLBACK;--事務回滾 set r_result = 0;--返回未修改數(shù)據(jù) ELSEIF (insert_count < 0) THEN ROLLBACK;--事務回滾 set r_result = -2;--返回未知錯誤 ELSE COMMIT;--提交,事務結(jié)束 set r_result = 1;--返回執(zhí)行成功 END IF;--結(jié)束IF語句 END IF;--結(jié)束IF語句 END;--結(jié)束儲存過程 $$--結(jié)束sql -- 存儲過程定義結(jié)束 DELIMITER ;--還原分隔符為; -- set @r_result=-3;--定義用戶變量 -- 執(zhí)行存儲過程 call execute_seckill(1003,13502178891,now(),@r_result); -- 獲取結(jié)果 select @r_result; -- 存儲過程 -- 1:存儲過程優(yōu)化:事務行級鎖持有的時間 -- 2:不要過度依賴存儲過程 -- 3:簡單的邏輯可以應用存儲過程 -- 4:QPS:一個秒殺單6000/qps
1.儲存過程參數(shù)
- IN:參數(shù)的值必須在調(diào)用存儲過程時指定,在存儲過程中修改該參數(shù)的值不能被返回,為默認值
- OUT:該值可在存儲過程內(nèi)部被改變,并可返回
- INOUT:調(diào)用時指定,并且可被改變和返回
- [IN|OUT|INOUT] 參數(shù)名 數(shù)據(jù)類型
- 比如: IN number INT
- 例子:
DELIMITER // CREATE PROCEDURE myproc(OUT s int) BEGIN SELECT COUNT(*) INTO s FROM students; END // DELIMITER ;
2.Mybatis調(diào)用儲存過程
<!-- statementType 聲明指向的是什么類型,其中CALLABLE是執(zhí)行存儲過程和函數(shù)的-->
<select id="killByProcedure" parameterType="map" statementType="CALLABLE">
call execute_seckill(
#{seckillId,jdbcType=BIGINT,mode=IN},
#{phone,jdbcType=BIGINT,mode=IN},
#{killTime,jdbcType=TIMESTAMP,mode=IN},
#{result,jdbcType=INTEGER,mode=OUT}
)
</select>
原文鏈接:http://suo.im/4p3v48 作者:薛勤






