4

次のように、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')問題は、execute ステートメントと deallocate ステートメントなど、繰り返すことがたくさんあることです....

私の質問は、このスクリプトをより少ない行で作成する他の方法はありませんか?

4

2 に答える 2

2

繰り返されるコードがたくさんあります。このような場合 (どの言語でも)、コードをリファクタリングする必要があります。

繰り返される部分を別のプロシージャに抽出し、必要なパラメータを渡し、メイン プロシージャを再コーディングして、抽出したコードを (再) 使用します。

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$$

次に、テーブルを作成してデータを入力します (1 回):

CREATE TABLE backup_table (
  table_name text);

INSERT INTO backup_table values ('BonInterne'), ('LigneBonInterne'), etc;

次に、これを簡単に行うことができます:

select do_backup(table_name)
from table_name;

バックアップからのテーブルの追加と削除は、テーブルへの行の挿入と削除と同じくらい簡単です。

于 2013-06-15T08:01:14.950 に答える
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();

注: 関数とイベントは 1 ステートメントのものです。DELIMITERしたがって、BEGIN ... ENDブロックを使用する必要はありません

于 2013-06-15T06:54:00.843 に答える