データベースを行単位で他のテーブルにコピーするSQL文のお話し。

テーブルをコピーする時にこんな書き方をするかと思います。

INSERT INTO `table`.`test_copy` SELECT * FROM `table`.`test`;

要は、insert文のvalueをselectで埋めてる感じ。
このやり方を初めて見た時はちょっと感動だったのが懐かしです。


行単位にコピーする場合は、まぁ行を指定するだけですね。
where句を追加して、

INSERT INTO `table`.`test_copy` SELECT * FROM `table`.`test` 
WHERE `id` = 123456;

これで指定のidを持つ行だけコピーできます。

INSERT INTO `table`.`test_copy` SELECT * FROM `table`.`test` 
WHERE `create` > '2009-08-01 00:00:00';

上の様に日付を指定すると、8/1以降に制作されたデータのみコピーとかもできます。

この書き方の何が良いかというと、やはり速度ですね。
プログラムでinsertをloopさせて投げるのと比べると、圧倒的に速い!

10,000件を超えるデータのinsertをphpでちまちまforで行うのはさすがにできませんよね。
でもDB側で処理を完結できるなら、十数カラム程度のデータを数万件コピーするぐらいなら、ごく普通にできます。

実用例だと

INSERT INTO `table`.`mail_list` SELECT null, {$id}, user_id, 0 FROM `table`.`users` 
WHERE `active` = 1 and `mail_error` < 2 limit 0, 10000;

こんな感じでユーザー情報をメール配信先リストにコピーしたりするのに使えます。
selectにjoinとか使ったり、軽い演算なんかも使えるので、かなり幅広い使い方ができます。たまにsql文を考えてると面白いですね。