1. 程式人生 > 其它 >mysql 函式 儲存過程 事件(event) job 模板

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 ;

建立事件模板:

-- ----------------------------
-- 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 ;
示例二