#这个是定义一个分隔符,因为一般是;结束,则会执行,而在存储过程中我们需要的是命令输入完毕执行
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 ;

 

posted on 2018-02-27 17:09  菜鸟你够了  阅读(15517)  评论(0编辑  收藏  举报