思考:一般我們的數據都是存儲在資料庫裡面,對於常規的CRUD操作都是用代碼實現,比如使用PHP做項目,所有的數據處理都需要主動操作代碼實現。如果我們現在有一項目,業務需要在用戶下單後,對用戶的訂單進行分潤處理,比如在每個月的21號,對上個月所有的訂單按設置的規則進行分潤處理,當然shll腳本也可以實 ...
思考:一般我們的數據都是存儲在資料庫裡面,對於常規的CRUD操作都是用代碼實現,比如使用PHP做項目,所有的數據處理都需要主動操作代碼實現。如果我們現在有一項目,業務需要在用戶下單後,對用戶的訂單進行分潤處理,比如在每個月的21號,對上個月所有的訂單按設置的規則進行分潤處理,當然shll腳本也可以實現,但是今天我們說的是如何通過資料庫“存儲過程”和“事件”來實現。
一、如下圖,是MySQL官網所介紹的https://dev.mysql.com/doc/refman/5.5/en/stored-objects.html
1、簡單的理解“存儲過程”就是我們平時寫的SQL的集合,裡面可能包含IF判斷或者posLoop:LOOP迴圈和我們平時寫PHP代碼差不多,就是為了實現某個操作(CRUD);
“事件”,就是我們設置的一個自動開關,可以按照我們設置的時間,比如每天12:00或者每分鐘處理一次(調用你寫的存儲過程)。
2、比如我們常用的Navicat的資料庫管理工具,第一個欄目是我們常用的“表”,第三個和第四個就是我們所說的“存儲過程”和“事件”。
二、簡單的需求。
1、比如我們有一張表 t_user,需要每2分鐘處理一下,如果 type 欄位值為 1,則把 num 的值修改為 500。
2、新建一個過程
3、具體SQL代碼。代碼大致說明一下:
:SQL裡面所有需要用到的變數,都需要先定義,所有我們先定義了一下三個變數。
:然後創建游標,相當於我們代碼裡面先獲取數據,獲取一個二維數組的 List ,並且把它放在 cur_test 裡面,如果游標內容執行完成,就將 done的值設置為 1 。
:打開游標,相當於開始獲取到這個變數。開始迴圈,相當於我們經常做的 foreach 迴圈數組操作,先判斷下,然後取出游標中的值,賦值給 定義好的變數。相當於我們key 和 value 鍵名 鍵值,然後判斷滿足即修改。
:最後結束迴圈的標示和釋放游標。
:可以點擊運行,如果沒有問題就可以查看是否更改數據,有問題會有提示錯誤。
BEGIN #處理t_user如果type = 1,則將num修改為200 #定義變數 DECLARE done int;#定義游標標記 DECLARE t_id int;#定義需要處理的id值 DECLARE t_type int;#定義記錄值類型 #創建游標,並存儲數據 DECLARE cur_test CURSOR FOR SELECT id,type FROM t_user LIMIT 500; #游標中的內容執行完後將done設置為1 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; #打開游標 OPEN cur_test; #執行迴圈 posLoop:LOOP #判斷是否結束迴圈 IF done = 1 THEN LEAVE posLoop; END IF; #取游標中的值 FETCH cur_test INTO t_id,t_type; #如果type = 1,則將num修改為200 IF t_type = 1 THEN #執行更新操作 UPDATE t_user SET num = 200 WHERE id = t_id; END IF; #結束迴圈 END LOOP posLoop; #釋放游標 CLOSE cur_test; END
4、創建 “事件”調用寫好的過程 p_t3()。調用 存儲過程 一般用 CALL + 過程名。
5、點擊保存時,可能提示 “event_scheduler = OFF” 未開啟,我們開啟下即可,指令如下。註意,每次重啟MySQL後,該值會設為 off 需要重新開啟一下。
#開啟 SET GLOBAL event_scheduler = ON; #關閉 SET GLOBAL event_scheduler = OFF;
最後:只要資料庫服務開啟,每分鐘都會調用一次p_t3(),實現裡面的業務規則。第一個簡單存儲過程加事件的調用,到此為止,至於為什麼SQL裡面這樣寫,我們往下看我的“MySQL實現定時清理過期數據”篇。