zoukankan      html  css  js  c++  java
  • mysql 函数 存储过程 事件(event) job 模板

    mysql的编程能力比sqlserver和mysql弱很多,万不得已尽量将这些东西转移到应用层。

    but,有时候小项目或项目刚开始尝试阶段,需要降低服务器成本,压缩项目规模。期初业务需求不清晰,也比较简单,为了快速成型也可以先凑合着用。

    创建函数模板:

    -- ----------------------------
    -- Function structure for f_get_childs
    -- ----------------------------
    DROP FUNCTION IF EXISTS `f_get_childs`;
    DELIMITER ;;
    CREATE FUNCTION `f_get_childs`(root_id INT) RETURNS varchar(1000) CHARSET utf8
    -- 有些工具如Navicat,只需要BEGIN到END这一段,SQLyog需要从DELIMITER到最后
    BEGIN
        DECLARE ptemp VARCHAR(1000);
        DECLARE ctemp VARCHAR(1000);
        SET ptemp = '#';
        SET ctemp =CAST(root_id AS CHAR);
        WHILE ctemp IS NOT NULL DO
            SET ptemp = CONCAT(ptemp,',',ctemp);
            SELECT GROUP_CONCAT(canton_id) 
              INTO ctemp 
              FROM sys_canton_info   
             WHERE FIND_IN_SET(parent_id,ctemp)>0; 
        END WHILE;  
        RETURN ptemp;  
    END
    ;;
    DELIMITER ;

    创建存储过程模板:

    -- ----------------------------
    -- Procedure structure for p_write_log
    -- ----------------------------
    DROP PROCEDURE IF EXISTS `p_write_log`;
    DELIMITER ;;
    CREATE PROCEDURE `p_write_log`(IN p_obj_name varchar(64), IN p_err_desc varchar(255), IN p_sql_err varchar(1000))
    BEGIN
      DECLARE v_error BOOL DEFAULT FALSE;
      DECLARE CONTINUE HANDLER FOR SQLWARNING,NOT FOUND, SQLEXCEPTION SET v_error = TRUE;
      START TRANSACTION;
      INSERT INTO sys_log(object_name, error_code, error_desc, trace)
      VALUES (p_obj_name, 'DB-FATAL', LEFT(p_err_desc, 255), LEFT(p_sql_err, 255));
      IF v_error = TRUE THEN
        ROLLBACK;
      ELSE
        COMMIT;
      END IF;
    END
    ;;
    DELIMITER ;
    -- ----------------------------
    -- Procedure structure for p_coupon_cdk_generate
    -- ----------------------------
    DROP PROCEDURE IF EXISTS `p_coupon_cdk_generate`;
    DELIMITER ;;
    CREATE PROCEDURE `p_coupon_cdk_generate`(IN r_num bigint)
    BEGIN
      DECLARE r_code varchar(32) charset utf8 default '';
      declare r_msg varchar(255) charset utf8 default 'success';
      declare l_count bigint default 0;
      declare l_code varchar(32) charset utf8 default '';
      declare l_counter bigint default 0;
      declare exit handler for sqlexception
        begin
          -- 先把错误取出来
          get diagnostics condition 1 r_code = returned_sqlstate, r_msg = message_text;
          rollback;
          call p_write_log('p_coupon_cdk_generate', concat('存储过程执行异常'),
                           concat('errcode:', ifnull(r_code, 'no-err-code'), ',errmsg:', ifnull(r_msg, 'no-err-msg')));
          select concat(ifnull(r_code, 'no-err-code'), '|', ifnull(r_msg, 'no-err-msg'));
          commit;
        end;
      start transaction;
      label_pro:
      begin
        set l_counter = r_num;
        while l_counter > 0 do
        set l_code = upper(right(MD5(uuid()), 6));
        if length(l_code + 0) = length(l_code) > 0 then --  通过随机的uu_id的MD5来取(纯数字的不要[遇到纯数字,跳出循环,等待下次执行])
          set r_msg = '纯数字,退出';
          leave label_pro;
        end if;
        select count(0) into l_count
        from xy_coupon_cdk t
        where t.cdk = l_code;
        if l_count > 0 then
          set r_msg = '重复的邀请码,退出';
          leave label_pro;
        end if;
    
        insert into xy_coupon_cdk(cdk)
        values (l_code);
    
        set l_counter = l_counter - 1;
        end while;
      end;
      commit;
      select concat('流程结束!', r_msg, ',条数:', r_num - l_counter);
    END
    ;;
    DELIMITER ;
    CREATE PROCEDURE `auto_fans_notify_handler`() 
    BEGIN
      DECLARE v_result VARCHAR(100) default "";
      DECLARE v_total_count INT DEFAULT 100;
      declare v_notify_limit int default 3;
      DECLARE v_queue_name VARCHAR(64) default "wx.fans.sync.notify";
      declare l_notify_id varchar(32);
      declare done int default false;
      DECLARE err_code CHAR(5) DEFAULT '00000';
      DECLARE err_msg TEXT;
      
      DECLARE items CURSOR FOR (SELECT t.notify_id
                FROM wx_fans_notify t
               WHERE t.notify_status in (20,30)
                 and t.notify_times <= v_notify_limit
                 AND t.next_notify_time < NOW()
                 AND t.next_notify_time > subdate(NOW(),INTERVAL 1 DAY)
                 LIMIT v_total_count);
      DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
      DECLARE EXIT HANDLER FOR SQLEXCEPTION
      BEGIN
        -- 先回滚,再保存错误日志
        GET DIAGNOSTICS CONDITION 1 err_code = RETURNED_SQLSTATE, err_msg = MESSAGE_TEXT;
        
        ROLLBACK; -- RollBack之后 error信息就取不到了(FUCK)(所以得先把错误取出来再回滚!!)
        
        CALL wx_p_write_log('auto_fans_notify_handler','执行异常',CONCAT(IFNULL(err_code,'null1'), IFNULL(err_msg,'null2')));
        SELECT CONCAT(IFNULL(err_code,'null1'), IFNULL(err_msg,'null2'));
        COMMIT;    
      END;  
      open items;
        xloop: Loop
          fetch items into l_notify_id;
          if done then
            leave xloop;
          end if;
          
      update wx_fans_notify t
         set t.notify_status    = 30,
             t.notify_times     = t.notify_times + 1,
             t.next_notify_time = adddate(NOW(),interval 5 minute)
       where t.notify_id = l_notify_id
         and t.notify_status in (20,30);
          
      if row_count() > 0 then
         set v_result = wx_f_message_task_create(v_queue_name,concat('{"notify_id":"',l_notify_id,'"}'));
          if (v_result = "success") then
            commit;
          else
            rollback;
          end if;  
      end if;
      end loop xloop;
      close items;
    END 

    创建事件模板:

    -- ----------------------------
    -- Event structure for auto_p_sys_data_clear
    -- ----------------------------
    DROP EVENT IF EXISTS `auto_p_sys_data_clear`;
    DELIMITER ;;
    CREATE EVENT `auto_p_sys_data_clear` ON SCHEDULE EVERY 1 HOUR STARTS '2019-09-27 15:29:39' ON COMPLETION PRESERVE ENABLE DO BEGIN
        DECLARE r_code CHAR(5) DEFAULT '00000';
        DECLARE r_msg TEXT CHARACTER SET utf8 DEFAULT '执行成功';
        DECLARE v_obj_name VARCHAR(100) DEFAULT 'p_sys_data_clear';
        DECLARE v_error BOOL DEFAULT FALSE;
        DECLARE v_start_time DATETIME DEFAULT NOW();
        DECLARE v_serial_no VARCHAR(100) DEFAULT CONCAT(v_obj_name, ':', REPLACE(UUID(), '-', ''));
        INSERT INTO `sys_job_log`(`object_name`, start_time, `serial_no`)
        VALUES (v_obj_name, v_start_time, v_serial_no);
        BEGIN
          #异常处理段
          DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
            BEGIN
              SET v_error = TRUE;
              GET DIAGNOSTICS CONDITION 1 r_code = RETURNED_SQLSTATE , r_msg = MESSAGE_TEXT;
            END;
          CALL p_sys_data_clear(); -- 这里将核心逻辑和event分离,event只管定时调度,核心逻辑尽量用存储过程实现
        END;
        -- 相当于记录调度日志
        UPDATE `sys_job_log` t 
           SET t.`status`        = IF(v_error, 90, 0),
               t.`end_time`      = NOW(),
               t.`duration_time` = TIMESTAMPDIFF(SECOND, v_start_time, NOW()),
               t.`result_msg`    = CONCAT(r_code, '|', r_msg)
         WHERE t.`serial_no` = v_serial_no
           AND t.`object_name` = v_obj_name
           AND t.`status` = 30;
      END
    ;;
    DELIMITER ;
    示例一
    -- ----------------------------
    -- Event structure for auto_p_order_sync
    -- ----------------------------
    DROP EVENT IF EXISTS `auto_p_order_sync`;
    DELIMITER ;;
    CREATE EVENT `auto_p_order_sync` ON SCHEDULE EVERY 3 SECOND STARTS '2019-09-27 15:42:25' ON COMPLETION PRESERVE ENABLE DO BEGIN
      DECLARE r_code CHAR(5) DEFAULT '00000';
      DECLARE r_msg TEXT CHARACTER SET utf8 DEFAULT '执行成功';
      DECLARE v_obj_name VARCHAR(100) DEFAULT 'p_order_pool_sync';
      DECLARE v_error BOOL DEFAULT FALSE;
      DECLARE v_start_time DATETIME DEFAULT NOW();
      DECLARE v_serial_no VARCHAR(100) DEFAULT '';
      DECLARE v_step INT DEFAULT 0;
      
      SELECT t.serial_no
        INTO v_serial_no
        FROM sys_job_log t
       WHERE t.object_name = 'p_order_pool_sync'
         AND t.start_time >= CURRENT_DATE()
       ORDER BY t.log_id DESC
       LIMIT 1;
      
      IF v_serial_no IS NULL OR v_serial_no = '' THEN
        SET v_serial_no = CONCAT(v_obj_name, ':', REPLACE(UUID(), '-', ''));
        INSERT INTO `sys_job_log`(`object_name`, start_time, `serial_no`)
        VALUES (v_obj_name, v_start_time, v_serial_no);
      END IF;
      
      BEGIN
        #异常处理段
        DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
          BEGIN
            SET v_error = TRUE;
            GET DIAGNOSTICS CONDITION 1 r_code = RETURNED_SQLSTATE , r_msg = MESSAGE_TEXT;
          END;
        SET v_step = v_step + 1;
        CALL p_order_goods_sync();
        SET v_step = v_step + 1;
        CALL p_order_recharge_sync();
        SET v_step = v_step + 1;
        CALL p_order_crp_coupon_sync();
      END;
      -- 同示例一
      UPDATE `sys_job_log` t
         SET t.`status`        = IF(v_error, 90, 0),
             t.`end_time`      = NOW(),
             t.`duration_time` = TIMESTAMPDIFF(SECOND, v_start_time, NOW()),
             t.`result_msg`    = CONCAT(v_step, '-', r_code, '|', r_msg)
       WHERE t.`serial_no` = v_serial_no
         AND t.`object_name` = v_obj_name;
    END
    ;;
    DELIMITER ;
    示例二

    关于事件启停,状态的一些SQL:

    SHOW VARIABLES LIKE 'event_scheduler';

    SHOW GLOBAL VARIABLES LIKE "event_scheduler";

    SET GLOBAL event_scheduler=1;

    SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST;

    SELECT * FROM wx_message_task;

    SHOW ERRORS;

    SHOW CREATE event exp_account_sync;

    SHOW EVENTS;

    -- 开启某事件:
    ALTER EVENT e_test ON COMPLETION PRESERVE ENABLE;

    -- 关闭某事件:
    ALTER EVENT e_test ON COMPLETION PRESERVE DISABLE;

  • 相关阅读:
    37. Sudoku Solver(js)
    36. Valid Sudoku(js)
    35. Search Insert Position(js)
    34. Find First and Last Position of Element in Sorted Array(js)
    33. Search in Rotated Sorted Array(js)
    32. Longest Valid Parentheses(js)
    函数的柯里化
    俞敏洪:我和马云就差了8个字
    vue路由传值params和query的区别
    简述vuex的数据传递流程
  • 原文地址:https://www.cnblogs.com/Denny_Yang/p/15693291.html
Copyright © 2011-2022 走看看