mysql存儲過程


#這個是定義一個分隔符,因為一般是;結束,則會執行,而在存儲過程中我們需要的是命令輸入完畢執行
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 ;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM