我使用MySQL中的事件调度程序创建了一个自动备份,如下所示:
DELIMITER $$
CREATE DEFINER=`root`@`localhost` EVENT `Backup`
ON SCHEDULE EVERY 1 WEEK
STARTS '2013-06-14 18:19:02' ON COMPLETION NOT PRESERVE ENABLE
DO
BEGIN
SET @sql_text1 = CONCAT("SELECT * FROM BonInterne INTO OUTFILE '/home/aimad/GestionStock/" , DATE_FORMAT( NOW(), '%Y%m%d') , "BonInterne.csv'" );
SET @sql_text2 = CONCAT("SELECT * FROM LigneBonInterne INTO OUTFILE '/home/aimad/GestionStock/" , DATE_FORMAT( NOW(), '%Y%m%d') , "LigneBonInterne.csv'" );
SET @sql_text3 = CONCAT("SELECT * FROM BonExterne INTO OUTFILE '/home/aimad/GestionStock/" , DATE_FORMAT( NOW(), '%Y%m%d') , "BonExterne.csv'" );
SET @sql_text4 = CONCAT("SELECT * FROM LigneBonExterne INTO OUTFILE '/home/aimad/GestionStock/" , DATE_FORMAT( NOW(), '%Y%m%d') , "LigneBonExterne.csv'" );
SET @sql_text5 = CONCAT("SELECT * FROM BonEntrée INTO OUTFILE '/home/aimad/GestionStock/" , DATE_FORMAT( NOW(), '%Y%m%d') , "BonEntrée.csv'" );
SET @sql_text6 = CONCAT("SELECT * FROM LigneBonEntrée INTO OUTFILE '/home/aimad/GestionStock/" , DATE_FORMAT( NOW(), '%Y%m%d') , "LigneBonEntrée.csv'" );
SET @sql_text7 = CONCAT("SELECT * FROM Inventaire INTO OUTFILE '/home/aimad/GestionStock/" , DATE_FORMAT( NOW(), '%Y%m%d') , "Inventaire.csv'" );
SET @sql_text8 = CONCAT("SELECT * FROM LigneInterventaire INTO OUTFILE '/home/aimad/GestionStock/" , DATE_FORMAT( NOW(), '%Y%m%d') , "LigneInventaire.csv'" );
PREPARE s1 FROM @sql_text;
PREPARE s2 FROM @sql_text;
PREPARE s3 FROM @sql_text;
PREPARE s4 FROM @sql_text;
PREPARE s5 FROM @sql_text;
PREPARE s6 FROM @sql_text;
PREPARE s7 FROM @sql_text;
PREPARE s8 FROM @sql_text;
EXECUTE s1;
EXECUTE s2;
EXECUTE s3;
EXECUTE s4;
EXECUTE s5;
EXECUTE s6;
EXECUTE s7;
EXECUTE s8;
DEALLOCATE PREPARE s1;
DEALLOCATE PREPARE s2;
DEALLOCATE PREPARE s3;
DEALLOCATE PREPARE s4;
DEALLOCATE PREPARE s5;
DEALLOCATE PREPARE s6;
DEALLOCATE PREPARE s7;
DEALLOCATE PREPARE s8;
END $$
DELIMITER ;
问题是有很多事情重复,例如DATE_FORMAT( NOW(), '%Y%m%d')
以及执行语句和释放语句......
我的问题是,是否有其他方法可以用更少的行创建这个脚本?
答案 0 :(得分:2)
你有很多重复的代码。在这种情况下(使用任何语言),您需要refactor您的代码。
将重复的部分提取到一个单独的过程中,传递任何必要的参数,并重新编写主程序以(重新)使用提取的代码。
DELIMITER $$
CREATE PROCEDURE DO_BACKUP(table_name text)
BEGIN
SET @sql = CONCAT("SELECT * FROM ", table_name,
" INTO OUTFILE '/home/aimad/GestionStock/" ,
DATE_FORMAT( NOW(), '%Y%m%d') , table_name, ".csv'" );
PREPARE s1 FROM @sql;
EXECUTE s1;
DEALLOCATE PREPARE s1;
END$$
CREATE DEFINER=`root`@`localhost` EVENT `Backup`
ON SCHEDULE EVERY 1 WEEK
STARTS '2013-06-14 18:19:02' ON COMPLETION NOT PRESERVE ENABLE
DO
BEGIN
CALL DO_BACKUP('BonInterne');
CALL DO_BACKUP('LigneBonInterne');
CALL DO_BACKUP('BonExterne');
CALL DO_BACKUP('LigneBonExterne');
CALL DO_BACKUP('BonEntrée');
CALL DO_BACKUP('LigneBonEntrée');
CALL DO_BACKUP('Inventaire');
CALL DO_BACKUP('LigneInterventaire');
END $$
DELIMITER ;
它还可以使您的代码更易于阅读和维护。看看添加另一个表是多么容易。
一旦像这样重构,您可以通过存储在表格中的值轻松地驱动它。特别是如果您将过程更改为函数:
CREATE FUNCTION DO_BACKUP(table_name text)
RETURNS text
BEGIN
-- as above
RETURN NULL;
END$$
然后创建并填充一个表(一次):
CREATE TABLE backup_table (
table_name text);
INSERT INTO backup_table values ('BonInterne'), ('LigneBonInterne'), etc;
然后你可以这样做:
select do_backup(table_name)
from table_name;
从备份中添加和删除表就像从表中插入和删除行一样简单。
答案 1 :(得分:1)
这就是你能做的。
首先让我们创建一个辅助函数,给定一个索引将返回一个表名
CREATE FUNCTION tname_from_idx(INT idx)
RETURNS VARCHAR(64)
RETURN CASE idx
WHEN 1 THEN 'BonInterne'
WHEN 2 THEN 'LigneBonInterne'
WHEN 3 THEN 'BonExterne'
WHEN 4 THEN 'LigneBonExterne'
WHEN 5 THEN 'BonEntrée'
WHEN 6 THEN 'LigneBonEntrée'
WHEN 7 THEN 'Inventaire'
WHEN 8 THEN 'LigneInterventaire'
ELSE 'n/a'
END;
其次让我们将备份代码包装到存储过程中,这样每次我们想要更改备份逻辑时都不会更改事件
DELIMITER $$
CREATE PROCEDURE do_backup()
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE tname VARCHAR(64) DEFAULT 'n/a';
SET tname = tname_from_idx(i);
WHILE tname <> 'n/a' DO
SET @sql = CONCAT('SELECT * FROM ', tname, ' INTO OUTFILE \'/home/aimad/GestionStock/', DATE_FORMAT(CURDATE(), '%Y%m%d'), tname, '.csv\'');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET i = i + 1;
SET tname = tname_from_idx(i);
END WHILE;
END$$
DELIMITER ;
就是这样。现在,您只需从事件中调用此存储过程。
CREATE DEFINER=`root`@`localhost` EVENT `Backup`
ON SCHEDULE EVERY 1 WEEK STARTS CURDATE() + INTERVAL 22 HOUR
DO CALL do_backup();
注意:我们的函数和事件是一个语句。因此,他们不需要使用DELIMITER
和BEGIN ... END
块