mysql儲存過程遊標,計算儀器近期維保時間
阿新 • • 發佈:2020-12-23
mysql儲存過程遊標,計算儀器近期維保時間
最近工作遇到的問題,本來打算寫一個java api在外面計算維保時間然後新增到工單表中,後來發現數據量大的時候太慢了,程式會一直訪問資料庫。所以乾脆在內部寫,順便記錄下。
(1)mysql遊標簡單入門
概念就是在儲存過程中遍歷結果集。 以前我用分頁也實現過,現在看來,真是太蠢了。
遊標的使用方式:
1):建立遊標
declare <遊標名>CURSOR FOR select * from <表名>;
2):開啟遊標:
open <遊標名> ;
3):屬性賦值:
FETCH <遊標名字> into <變數名>;
declare vUid int(11) default ‘0’;
declare <遊標名>CURSOR FOR select uid from <表名>;
FETCH <遊標名字> into vUid ;
這樣就可以賦值了。
4):關閉遊標
close mycursor;
(2)主題!根據儀器維保時間於維保規則建立近期維保工單。運用了些mysql函式這裡說一下。
now():獲取當天時間。
DATE_FORMAT(now() ,’%Y-%m-%d %H:%i:%s’):時間規則。
round():取整。
ADDDATE(‘時間’,interval <需新增天數>day);時間加法
if exists(select * from where)then :查詢通過判斷表中資料來判斷是否滿足if條件。
begin -- 宣告所需賦值變數,這裡有個點需要說一下:宣告變數於宣告遊標之間不能對變數進行賦值。好像區域塊的原因具體我也不太清楚。 declare vUid int(11) default '0'; declare vDone int(11) default '0'; declare vDevcode varchar(100) default ''; declare vStartTime varchar(100) default ''; declare vEndTime varchar(100) default ''; declare vCreateTime varchar(100) default ''; declare vFirstDay int(11) default '0'; declare vRule varchar(100) default ''; declare vWeekPeriods varchar(100) default ''; declare vCustomCode varchar(100) default ''; declare vDefenId int(11) default '0'; declare vOverdueData varchar(100) default ''; declare vCon int(11) default '0'; -- 宣告遊標左聯出需要的資料。 declare mycursor CURSOR FOR select a.id , a.dev_number, a.start_time , a.end_time , a.create_time , a.first_day , b.rule, b.week_periods, c.owner_customer_number from biosys_device_defenddate a left join biosys_device_defend b on a.defcode_id = b.id left join bio_device c on a.dev_number = c.device_number ; DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone=1; -- 開啟遊標 open mycursor; -- 這裡需要注意的點 into後面的需要賦值的值要與select查出的數量順序一致 不然無法進入迴圈體。 FETCH mycursor into vDefenId ,vDevcode ,vStartTime ,vEndTime ,vCreateTime ,vFirstDay ,vRule ,vWeekPeriods ,vCustomCode; -- 下面這些的就是生成維保工單的邏輯演算法vFirstDay是資料表中取出維保日期偏移數值不能大於一週,所以這裡判斷取模。 if vFirstDay>7 then set vFirstDay = 7%vFirstDay; end if ; -- 進去遊標迴圈體這裡會把資料集迴圈出來。 while vDone<> 1 do -- 判斷當天是否小於維保最後維保日期 if DATE_FORMAT(now() ,'%Y-%m-%d %H:%i:%s')<DATE_FORMAT(vEndTime,'%Y-%m-%d %H:%i:%s')then -- 開啟跳出迴圈 相當於java的break;要點必須包住while迴圈體 outer_label: BEGIN -- 這裡根據維保規則計算還需維保幾次,結束時間減第一次維保時間除以維保週期, --這要就可以算出需要維保的時間了,計算出的 vStartTime+偏移+維保週期 = 近期維保時間。 while vCon < round((to_days(DATE_FORMAT(vEndTime,'%Y-%m-%d'))-to_days(DATE_FORMAT(vStartTime,'%Y-%m-%d')))/ (vWeekPeriods*7)) do set vOverdueData = date_format(ADDDATE(ADDDATE(date_format(vStartTime,'%Y-%m-%d'),interval vFirstDay day),interval vWeekPeriods*7 day),'%Y-%m-%d'); if ROUND((to_days(DATE_FORMAT(vOverdueData,'%Y-%m-%d'))-to_days(DATE_FORMAT(now(),'%Y-%m-%d'))))<=7 then if exists(select a.pk_id from bio_device a where a.device_number = vDevcode)then insert into biosys_workorder(`workorder_type_id` ,`desc`,`memb_id`,`custom_id` ,`title`,`code`,`create_date` ,`exp_date`,`workerorder_bugtype_id` ,`level` ,`device_number`,`inspection`,`src_id`,`expected_date`,`ref_code`) values(5,'',1,vCustomCode ,'裝置維保' ,concat('BIO',_nextval('WO_ID')) ,DATE_FORMAT(now() ,'%Y-%m-%d %H:%i:%s') ,DATE_FORMAT( DATE_ADD(now(),INTERVAL 3 DAY) ,'%Y-%m-%d') ,1,1,vDevcode,'',4, DATE_FORMAT(vOverdueData ,'%Y-%m-%d %H:%i:%s') ,0); end if ; else LEAVE outer_label; end if ; set vCon = vCon+1; set vStartTime = vOverdueData; end while ; END outer_label; end if; FETCH mycursor into vDefenId,vDevcode ,vStartTime ,vEndTime ,vCreateTime ,vFirstDay ,vRule ,vWeekPeriods ,vCustomCode; end while ; close mycursor; END
到這裡就結束了。