データベースの運用中、特定の接頭辞を持つ複数のテーブルに対して、カラムの追加や削除といった変更を一度に適用したい場合があります。MySQLでは、information_schema.TABLES を参照することで、対象となるテーブル操作用SQLを動的に生成し、一括処理を行うことが可能です。
※ 実行前に必ずデータベースのバックアップを取得し、検証環境で動作を確認してください。
1. 複数テーブルへのカラム一括追加
特定の接頭辞(例: v_content_)を持つ全てのテーブルに、新しいカラム author_id を追加するためのSQL文を生成します。
SELECT CONCAT('ALTER TABLE ', table_name, ' ADD COLUMN author_id INT(11) DEFAULT NULL COMMENT "作成者ID";')
FROM information_schema.TABLES
WHERE table_name LIKE 'v_content_%'
AND table_schema = 'your_database_name';
このクエリを実行すると、対象テーブルごとの ALTER TABLE 文がリストとして出力されます。これらをコピーして実行することで、一括更新が完了します。
2. 生成されたSQLの一括実行方法
方法A:sourceコマンドを利用する
生成されたSQLをテキストファイル(例: update_schema.sql)として保存し、MySQLクライアントから読み込みます。
-- MySQLにログインした状態で実行
source /path/to/update_schema.sql;
方法B:プログラム(PHP等)による逐次実行
アプリケーション側で動的にSQLを取得し、ループ処理で実行する方法です。
// PDOを使用した実装例
$stmt = $pdo->prepare("SELECT CONCAT('ALTER TABLE ', table_name, ' ADD COLUMN author_id INT(11);') as sql_cmd
FROM information_schema.TABLES
WHERE table_name LIKE 'v_content_%'");
$stmt->execute();
$commands = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($commands as $row) {
$pdo->exec($row['sql_cmd']);
}
方法C:ストアドプロシージャによる自動化
MySQL内部のループ処理を用いて実行する例です(簡易的な繰り返し処理の構造)。
DELIMITER //
CREATE PROCEDURE BatchUpdateExample()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE target_sql TEXT;
-- ここでは例として単純な更新クエリを想定
DECLARE cur CURSOR FOR SELECT CONCAT('UPDATE ', table_name, ' SET status = 1;')
FROM information_schema.TABLES WHERE table_name LIKE 'v_content_%';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop: LOOP
FETCH cur INTO target_sql;
IF done THEN
LEAVE read_loop;
END IF;
-- 動的SQLの実行
SET @s = target_sql;
PREPARE stmt FROM @s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP;
CLOSE cur;
END //
DELIMITER ;
CALL BatchUpdateExample();
3. テーブルの一括削除
不要になった古いバックアップテーブルや一時テーブルを一括で削除するSQLを生成します。
SELECT CONCAT('DROP TABLE ', table_name, ';')
FROM information_schema.TABLES
WHERE table_name LIKE 'tmp_2023_%';
出力された DROP TABLE 文の内容を慎重に確認した上で実行してください。
4. テーブルの複製とデータ移行
一括処理の前後でテーブル構造のコピーやバックアップを行う際に便利なコマンドです。
構造のみをコピー
CREATE TABLE destination_tbl LIKE source_tbl;
構造とデータ全体をコピー
CREATE TABLE destination_tbl SELECT * FROM source_tbl;
特定の条件に合致するデータのみを別のテーブルへ挿入
INSERT INTO archive_tbl (id, title, created_at)
SELECT id, title, created_at
FROM original_tbl
WHERE created_at < '2023-01-01';