#這個是定義一個分隔符,因為一般是;結束,則會執行,而在存儲過程中我們需要的是命令輸入完畢執行 DELIMITER $$ DROP PROCEDURE IF EXISTS `refresh_device_city`$$ CREATE PROCEDURE refresh_device_city(IN device_id BIGINT,IN table_num INT) BEGIN #定義變量 DECLARE locationTableName VARCHAR(255); DECLARE delete_sql VARCHAR(200); DECLARE insert_sql VARCHAR(2000); DECLARE err INT DEFAULT 0; -- 如果出現異常,會自動處理並rollback DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK ; START TRANSACTION; SET locationTableName= CONCAT('lbs_device_location_', table_num); SET @delete_sql = CONCAT('DELETE FROM lbs_device_city WHERE device_id=',device_id); SET @insert_sql = CONCAT('INSERT INTO LBS_DEVICE_CITY (device_id,city,into_city_time,create_time) SELECT ',device_id,',a.city city,a.ltime ltime,NOW() FROM( SELECT MIN(a.city) city,MIN(a.ltime) ltime FROM ( SELECT CASE WHEN a.city!=@city THEN @i:=@i+1 ELSE @i END i, CASE WHEN a.city!=@city THEN @city:=a.city ELSE @city END tcity, a.city city,a.ltime ltime FROM ( SELECT a.CITY city,a.LOCATION_TIME ltime FROM ',locationTableName,' a WHERE a.DEVICE_ID = ',device_id,' AND a.city !=\'\' AND a.CITY != \'未知\' ORDER BY a.LOCATION_TIME ASC) a ,(SELECT @i:=-1,@city:=\'未知\') b )a WHERE a.i != -1 GROUP BY a.i ) a ORDER BY a.ltime ASC'); #執行SQL語句 PREPARE delstmt FROM @delete_sql; EXECUTE delstmt; DEALLOCATE PREPARE delstmt; PREPARE insstmt FROM @insert_sql; EXECUTE insstmt; DEALLOCATE PREPARE insstmt; COMMIT; END$$ DELIMITER ; DELIMITER $$ DROP PROCEDURE IF EXISTS `refresh_all_device_city`$$ CREATE PROCEDURE refresh_all_device_city() BEGIN #查詢所有在設備城市表中有數據的設備和對應定位所在表的編號 #循環設備,刪除設備所有城市記錄,重新插入數據,調用另一個存儲過程 /*這種寫法也可以:DECLARE done INT DEFAULT FALSE;*/ DECLARE done INT DEFAULT 0; /*用於判斷是否結束循環*/ DECLARE deviceid BIGINT; /*用於存儲結果集S_S的記錄(因為我這里S_S的記錄只有一列且為bigint類型)*/ DECLARE tablenum INT; /*定義游標*/ DECLARE idCur CURSOR FOR SELECT a.device_id,b.table_num FROM lbs_device_city a,lbs_device b WHERE a.device_id=b.id GROUP BY device_id; /*定義 設置循環結束標識done值怎么改變 的邏輯*/ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; /*done = true;亦可*/ OPEN idCur; /*打開游標*/ REPEAT FETCH idCur INTO deviceid,tablenum; /*這部分可以看看書,還可以fetch多列(假設結果集S_S的記錄不是單列的話)*/ IF NOT done THEN /*數值為非0,MySQL認為是true*/ CALL refresh_device_city(deviceid,tablenum); END IF; UNTIL done END REPEAT; CLOSE idCur; /*關閉游標*/ SELECT deviceid; END$$ DELIMITER ; CALL refresh_all_device_city();
/**處理單個設備的數據插入到定位統計表中*/ DROP PROCEDURE IF EXISTS count_device_location; DELIMITER $$ -- 分隔符 因為一般是;結束,則會執行,而在存儲過程中我們需要的是命令輸入完畢執行 CREATE PROCEDURE count_device_location(IN deviceid BIGINT,IN tablenum BIGINT)-- 接收參數,根據設備ID,查詢對應的設備編號, BEGIN -- 多個列的情況下似乎只能用 into 方式 DECLARE insert_sql VARCHAR(4000); DECLARE err INT DEFAULT 0; -- 如果出現異常,會自動處理並rollback DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK ; START TRANSACTION; SELECT `device_id`, `org_key` INTO @deviceno, @orgkey FROM lbs_device WHERE `id`=deviceid; -- 注意參數不能與表中任何列名相同,否則不會取到參數 /*執行插入SQL*/ -- 如果出現異常,會自動處理並rollback SET @insert_sql = CONCAT('INSERT INTO LBS_DEVICE_LOCATION_COUNT (DEVICE_NO,ORG_KEY,START_TIME,END_TIME,LOCATION_COUNT) SELECT \'',@deviceno ,'\',\'',@orgkey,'\',CONCAT(b.location_count_time,\':00:00\'),DATE_ADD(b.location_count_time,INTERVAL 1 HOUR),b.num FROM (SELECT COUNT(a.id) num,a.location_count_time FROM (SELECT DATE_FORMAT(location_time,\'%Y-%m-%d %H\') location_count_time,id FROM lbs_device_location_',tablenum,' WHERE device_id=',deviceid,') a GROUP BY a.location_count_time) b'); #執行SQL語句 PREPARE insstmt FROM @insert_sql; EXECUTE insstmt; DEALLOCATE PREPARE insstmt; COMMIT; END$$ DELIMITER ; CALL count_device_location(29632,2); DELIMITER $$ DROP PROCEDURE IF EXISTS `query_location_device_table`$$ CREATE PROCEDURE query_location_device_table() BEGIN #查詢所有在設備城市表中有數據的設備和對應定位所在表的編號 #循環設備,刪除設備所有城市記錄,重新插入數據,調用另一個存儲過程 /*這種寫法也可以:DECLARE done INT DEFAULT FALSE;*/ DECLARE done INT DEFAULT 0; /*用於判斷是否結束循環*/ DECLARE deviceid BIGINT; /*用於存儲結果集*/ /*定義游標*/ DECLARE idCur CURSOR FOR SELECT device_id FROM lbs_device_location_1 GROUP BY device_id ; /*定義 設置循環結束標識done值怎么改變 的邏輯*/ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; /*done = true;亦可*/ OPEN idCur; /*打開游標*/ REPEAT FETCH idCur INTO deviceid; /*fetch多列*/ IF NOT done THEN /*數值為非0,MySQL認為是true*/ CALL count_device_location(deviceid,1); END IF; UNTIL done END REPEAT; CLOSE idCur; /*關閉游標*/ END$$ DELIMITER ;
查詢預警表中所有的記錄,然后循環每一條,查詢它是否有未結束的跟蹤號,如果沒有,則將該預警的狀態置為無效
DELIMITER $$ USE `lbs_test`$$ DROP PROCEDURE IF EXISTS `clean_invalid_one_warning`$$ CREATE DEFINER=`lbs_test`@`%` PROCEDURE `clean_invalid_one_warning`(IN warning_id BIGINT) BEGIN #查詢這個預警是否有未結束的跟蹤號 SET @select_stmt=CONCAT('SELECT COUNT(b.id) INTO @cnt1 FROM lbs_warning a INNER JOIN `lbs_track_register` b ON a.`ORG_KEY`=b.`ORG_APIKEY` AND a.`TRACK_NO`=b.`TRACK_NO` WHERE a.id=',warning_id ,' AND (b.`TRACK_END_TIME`>NOW() OR b.`TRACK_END_TIME` IS NULL) '); PREPARE stmt FROM @select_stmt; EXECUTE stmt; DEALLOCATE PREPARE stmt; SELECT @cnt1; #如果查詢到未結束的跟蹤號,開啟一個事物,修改它為結束 IF (@cnt1=0) THEN #開啟事物修改 START TRANSACTION; #執行SQL語句 SET @update_stmt=CONCAT('UPDATE LBS_WARNING SET `STATUS`=0 WHERE ID=',warning_id); PREPARE upstmt FROM @update_stmt; EXECUTE upstmt; DEALLOCATE PREPARE upstmt; COMMIT; END IF; END$$ DELIMITER ; DELIMITER $$ USE `lbs_test`$$ DROP PROCEDURE IF EXISTS `clean_invalid_warning`$$ CREATE DEFINER=`lbs_test`@`%` PROCEDURE `clean_invalid_warning`() BEGIN #查詢所有未結束的預警 #循環每個預警,查詢它是否有未結束的跟蹤號 #如果沒有,則修改該預警為無效 /*這種寫法也可以:DECLARE done INT DEFAULT FALSE;*/ DECLARE done INT DEFAULT 0; /*用於判斷是否結束循環*/ DECLARE warningid BIGINT; /*用於存儲結果集*/ /*定義游標*/ DECLARE idCur CURSOR FOR SELECT id FROM lbs_warning WHERE `status`='1' ; /*定義 設置循環結束標識done值怎么改變 的邏輯*/ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; /*done = true;亦可*/ OPEN idCur; /*打開游標*/ REPEAT FETCH idCur INTO warningid; /*fetch賦值*/ IF NOT done THEN /*數值為非0,MySQL認為是true*/ /**根據預警ID查詢它是否有未結束的跟蹤號*/ CALL clean_invalid_one_warning(warningid); END IF; UNTIL done END REPEAT; CLOSE idCur; /*關閉游標*/ END$$ DELIMITER ;