zoukankan      html  css  js  c++  java
  • 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 ;
  • 相关阅读:
    mysql免安装
    记一次电脑DNS被劫持
    小程序中page声明周期onShow
    微信公众号调试
    wx.navigateTo()
    mongodb 数据库安装
    小程序中使用坐标获得地区名称
    小程序 <include >
    记一点typescript whitespace rule
    小程序<template>的使用
  • 原文地址:https://www.cnblogs.com/Ebird/p/6652279.html
Copyright © 2011-2022 走看看