地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

【MySQL】mysql can't reopen union

MySQLの仕様として一時テーブルはテーブルを再オープンできないので一つのクエリ内では複数回参照するということができない。

mysql> desc employee_table;
+---------------+--------------+------+-----+---------+----------------+
| Field         | Type         | Null | Key | Default | Extra          |
+---------------+--------------+------+-----+---------+----------------+
| ID            | int          | NO   | PRI | NULL    | auto_increment |
| employee_name | varchar(255) | NO   | MUL | NULL    |                |
| phone_number  | varchar(16)  | YES  |     | NULL    |                |
| phone_number2 | varchar(15)  | YES  |     | NULL    |                |
+---------------+--------------+------+-----+---------+----------------+

こんなテーブルがあるとして以下のようにUNIONするとCan't reopen table: 'temporary_employee_table'というエラーになる。

mysql> CREATE TEMPORARY TABLE temporary_employee_table AS
    -> SELECT * FROM employee_table;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM temporary_employee_table
    -> UNION
    -> SELECT * FROM temporary_employee_table;
ERROR 1137 (HY000): Can't reopen table: 'temporary_employee_table'

この動作自体はドキュメントにもTEMPORARY テーブルに関する問題というセクションに書いてある。回避策としてはトランザクション内でSELECT INSERTとかしてテーブルを作ってUNIONを実行しないようにする方法などがある。ただ最近あったのはMySQL4.0では動くが5系にした途端に落ちるというのがあった。4系だとこの制限がないのかな?と思ってドキュメントを探して調べてみたら同じような制限が当時もありそうというのが書いてあった。

www.mysql.gr.jp

テンポラリーテーブルは一度のクエリで一回しか使用できません。例えば、次のようなものは動きません。
mysql> SELECT * FROM temporary_table, temporary_table AS t2;

あれ、じゃあ4.0の時にもUNIONで落ちるのではと思ったが同じクエリを実行してもエラーにならなかった。色々調べてみたがどこからUNIONで落ちるようになったかは見つけられなかったが5.0の時のバグレポートとして以下のissueが作られていた。4.0と4.1では動いていたとも書いてあるが5.0で何か変わったとなっているがどうしてそうなったのかまではわからなかった。

bugs.mysql.com