mysql建立存儲過程實戰,歷史表數據遷移,歷史表自動分區,

首先是寫一個存儲過程,還是比較簡單的,主要是網上有很多現成的,大部分有點錯誤。下邊的是實際應用過程中實戰有效的。沒有錯誤的。

首先是存儲過程展示;

DELIMITER $$

DROP PROCEDURE IF EXISTS `create_Partition`$$

CREATE DEFINER=`root`@`%` PROCEDURE `create_Partition`(IN databaseName VARCHAR(50),IN tableName VARCHAR(50))
L_END:BEGIN       
     DECLARE MAX_PARTITION_DESCRIPTION VARCHAR(255) DEFAULT 0;  
     DECLARE P_NAME VARCHAR(255) DEFAULT 0;         
     DECLARE P_DESCRIPTION VARCHAR(255) DEFAULT 0;     
     DECLARE i INT DEFAULT 1;  
     DECLARE ISEXIST_PARTITION VARCHAR(255) DEFAULT 0;   
        DECLARE MONTH_DAYS VARCHAR(5);
        DECLARE YEAR_NUM VARCHAR(10);
        DECLARE MONTH_NUM VARCHAR(5);
     SELECT PARTITION_NAME INTO ISEXIST_PARTITION FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = databaseName AND TABLE_NAME = tableName  LIMIT 1 ;  

     IF ISEXIST_PARTITION <=> "" THEN  
       SELECT "Partition table not is exist" AS "*****ERROR*****";  
       LEAVE  L_END;  
     END IF;  

     SELECT partition_description INTO MAX_PARTITION_DESCRIPTION  FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = databaseName AND TABLE_NAME = tableName ORDER BY partition_description DESC LIMIT 1;  


     IF MAX_PARTITION_DESCRIPTION <=> "" THEN  
       SELECT "Partition table is error" AS "*****ERROR*****";  
       LEAVE  L_END;  
     END IF;  


        select day(last_day(date_add(NOW(), interval 1 MONTH)))into MONTH_DAYS;

    SET MAX_PARTITION_DESCRIPTION = REPLACE(MAX_PARTITION_DESCRIPTION, '\'', '');  
    WHILE i <= MONTH_DAYS DO  
                        select date_format(date_add(last_day(NOW()),interval i day),'%Y-%m-%d') into P_DESCRIPTION;
          ## SET P_DESCRIPTION = adddate(MAX_PARTITION_DESCRIPTION, INTERVAL i day);  
           SET P_NAME = REPLACE(P_DESCRIPTION, '-', '');  
           SET @S=CONCAT('ALTER TABLE ',tableName,' ADD PARTITION  (PARTITION p',P_NAME,' VALUES LESS THAN (','\'',P_DESCRIPTION,'\'','))');  
           SELECT @S;  
           PREPARE stmt2 FROM @S;  
           EXECUTE stmt2;  
           DEALLOCATE PREPARE stmt2;  
           SET i = i + 1 ;  
    END WHILE;            
END L_END$$

DELIMITER ;

別看這麼長,實際用到的只是while部分。其餘部分就是判斷有效性和查詢數據,爲自動分區做準備數據用的。

寫好了存儲過程可以自己建一張表測試一下。

CREATE TABLE `realtable` (
  `id` int(10) unsigned NOT NULL COMMENT '表主鍵',
  `pid` int(10) unsigned NOT NULL COMMENT '產品ID',
  `price` decimal(15,2) NOT NULL COMMENT '單價',
  `num` int(11) NOT NULL COMMENT '購買數量',
  `uid` int(10) unsigned NOT NULL COMMENT '客戶ID',
  `atime` varchar(255) NOT NULL DEFAULT '',
  `utime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '修改時間',
  PRIMARY KEY (`id`,`atime`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
/*!50500 PARTITION BY RANGE  COLUMNS(atime)
(PARTITION p30 VALUES LESS THAN ('2018-07-09') ENGINE = InnoDB,
 PARTITION p31 VALUES LESS THAN ('2018-07-10') ENGINE = InnoDB,
 PARTITION p32 VALUES LESS THAN ('2018-07-11') ENGINE = InnoDB,
 PARTITION p33 VALUES LESS THAN ('2018-07-12') ENGINE = InnoDB,
 PARTITION p20180801 VALUES LESS THAN ('2018-08-01') ENGINE = InnoDB,
 PARTITION p20180802 VALUES LESS THAN ('2018-08-02') ENGINE = InnoDB,
 PARTITION p20180803 VALUES LESS THAN ('2018-08-03') ENGINE = InnoDB,
 PARTITION p20180804 VALUES LESS THAN ('2018-08-04') ENGINE = InnoDB,
 PARTITION p20180805 VALUES LESS THAN ('2018-08-05') ENGINE = InnoDB,
 PARTITION p20180806 VALUES LESS THAN ('2018-08-06') ENGINE = InnoDB,
 PARTITION p20180807 VALUES LESS THAN ('2018-08-07') ENGINE = InnoDB,
 PARTITION p20180808 VALUES LESS THAN ('2018-08-08') ENGINE = InnoDB,
 PARTITION p20180809 VALUES LESS THAN ('2018-08-09') ENGINE = InnoDB,
 PARTITION p20180810 VALUES LESS THAN ('2018-08-10') ENGINE = InnoDB,
 PARTITION p20180811 VALUES LESS THAN ('2018-08-11') ENGINE = InnoDB,
 PARTITION p20180812 VALUES LESS THAN ('2018-08-12') ENGINE = InnoDB,
 PARTITION p20180813 VALUES LESS THAN ('2018-08-13') ENGINE = InnoDB,
 PARTITION p20180814 VALUES LESS THAN ('2018-08-14') ENGINE = InnoDB,
 PARTITION p20180815 VALUES LESS THAN ('2018-08-15') ENGINE = InnoDB,
 PARTITION p20180816 VALUES LESS THAN ('2018-08-16') ENGINE = InnoDB,
 PARTITION p20180817 VALUES LESS THAN ('2018-08-17') ENGINE = InnoDB,
 PARTITION p20180818 VALUES LESS THAN ('2018-08-18') ENGINE = InnoDB,
 PARTITION p20180819 VALUES LESS THAN ('2018-08-19') ENGINE = InnoDB,
 PARTITION p20180820 VALUES LESS THAN ('2018-08-20') ENGINE = InnoDB,
 PARTITION p20180821 VALUES LESS THAN ('2018-08-21') ENGINE = InnoDB,
 PARTITION p20180822 VALUES LESS THAN ('2018-08-22') ENGINE = InnoDB,
 PARTITION p20180823 VALUES LESS THAN ('2018-08-23') ENGINE = InnoDB,
 PARTITION p20180824 VALUES LESS THAN ('2018-08-24') ENGINE = InnoDB,
 PARTITION p20180825 VALUES LESS THAN ('2018-08-25') ENGINE = InnoDB,
 PARTITION p20180826 VALUES LESS THAN ('2018-08-26') ENGINE = InnoDB,
 PARTITION p20180827 VALUES LESS THAN ('2018-08-27') ENGINE = InnoDB,
 PARTITION p20180828 VALUES LESS THAN ('2018-08-28') ENGINE = InnoDB,
 PARTITION p20180829 VALUES LESS THAN ('2018-08-29') ENGINE = InnoDB,
 PARTITION p20180830 VALUES LESS THAN ('2018-08-30') ENGINE = InnoDB,
 PARTITION p20180831 VALUES LESS THAN ('2018-08-31') ENGINE = InnoDB) */;

其中7月份是手動建的,其餘的是調用改存儲過程生成的。

調用SQL語句:

 CALL create_Partition('liuhua','realtable');

可能在調用過程中會報錯root不存在,此時需要授權一下。SQL語句如下。

grant all privileges on *.* to root@"%" identified by ".";

這樣就可以實現按照天自動分區。

存儲過程寫完了,分區效果實現了,那麼就可以寫一個事件去執行了。

DELIMITER $$
CREATE DEFINER=`root`@`%` EVENT `auto_set_partitions`
 ON SCHEDULE EVERY 1 MONTH STARTS '2018-08-11 17:18:00' 
ON COMPLETION PRESERVE ENABLE 
DO 
BEGIN  
        CALL create_Partition('liuhua','realtable');

    END $$
DELIMITER ;

注意:1 該存儲過程就幾乎不需要修改就可以直接使用;

           2 其中的時間字段是varcha類型的,其他的時間類型會報錯,類型不正確。

           3 可以修改的地方,存儲過程的嗎名字,和時間字段的格式。

具體的內容意思就不做詳細介紹了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章