例子
-- 秒殺執行存儲過程 DELIMITER $$ -- 將分隔符; 轉換為 $$ -- 定義存儲過程 -- 參數: in 輸入參數; out 輸出參數 -- row_count():返回上一條修改類型sql(delete,insert,update)的影響行數 -- row_count: 0:未修改數據; >0:表示修改的行數; <0:sql錯誤/未執行修改sql CREATE PROCEDURE `seckill`.`execute_seckill` (in v_seckill_id bigint,in v_phone bigint, in v_kill_time timestamp,out r_result int)--創建儲存過程 BEGIN-- 開始執行 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);--執行insert語句 select row_count() into insert_count;--返回影響行數 IF (insert_count = 0) THEN ROLLBACK;--事務回滾 set r_result = -1;--返回未修改數據 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;--執行update語句 select row_count() into insert_count;--返回影響行數 IF (insert_count = 0) THEN ROLLBACK;--事務回滾 set r_result = 0;--返回未修改數據 ELSEIF (insert_count < 0) THEN ROLLBACK;--事務回滾 set r_result = -2;--返回未知錯誤 ELSE COMMIT;--提交,事務結束 set r_result = 1;--返回執行成功 END IF;--結束IF語句 END IF;--結束IF語句 END;--結束儲存過程 $$--結束sql -- 存儲過程定義結束 DELIMITER ;--還原分隔符為; -- set @r_result=-3;--定義用戶變量 -- 執行存儲過程 call execute_seckill(1003,13502178891,now(),@r_result); -- 獲取結果 select @r_result; -- 存儲過程 -- 1:存儲過程優化:事務行級鎖持有的時間 -- 2:不要過度依賴存儲過程 -- 3:簡單的邏輯可以應用存儲過程 -- 4:QPS:一個秒殺單6000/qps
1.儲存過程參數
- IN:參數的值必須在調用存儲過程時指定,在存儲過程中修改該參數的值不能被返回,為默認值
- OUT:該值可在存儲過程內部被改變,并可返回
- INOUT:調用時指定,并且可被改變和返回
- [IN|OUT|INOUT] 參數名 數據類型
- 比如: IN number INT
- 例子:
DELIMITER // CREATE PROCEDURE myproc(OUT s int) BEGIN SELECT COUNT(*) INTO s FROM students; END // DELIMITER ;
2.Mybatis調用儲存過程
<!-- statementType 聲明指向的是什么類型,其中CALLABLE是執行存儲過程和函數的--> <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 作者:薛勤