MySQL 5.2, CentOS 6.4.
MySQL SELECT * fails on temporary table created by PREPARE using dynamic column and table names after first pass, when column name and table name are changed to different values from the first pass.
The work-around is to use a column alias that remains the same from pass to pass.
DROP PROCEDURE IF EXISTS test1;
DELIMITER $$
CREATE PROCEDURE test1( column_name VARCHAR(20), table_name VARCHAR(20) )
BEGIN
SET @prepared_stmt_arg = 'prepared_stmt_arg_value';
DROP TABLE IF EXISTS tmp1;
CREATE TEMPORARY TABLE tmp1
SELECT 1 AS col_tmp1;
DROP TABLE IF EXISTS tmp2;
CREATE TEMPORARY TABLE tmp2
SELECT 2 AS col_tmp2;
# drop tmp table if it exists
DROP TABLE IF EXISTS tmp_test1;
# prepared statement
SET @prepared_stmt =
CONCAT("
CREATE TEMPORARY TABLE tmp_test1
SELECT ? AS prepared_stmt_arg, ", column_name, " # AS constant_col_alias
FROM ", table_name, "
"); # END statement
# display prepared statement before executing it
SELECT @prepared_stmt;
# prepare the statement
PREPARE ps FROM @prepared_stmt;
# execute
EXECUTE ps USING @prepared_stmt_arg;
# deallocate
DEALLOCATE PREPARE ps;
# display
SELECT * FROM tmp_test1;
END $$
DELIMITER ;
The SELECT statement at the very end of the procedure fails. (You may need to scroll down to see the error message.)
mysql> CALL test1('col_tmp1', 'tmp1');
+---------------------------------------------------------------------------------------------------------------------------------+
| @prepared_stmt |
+---------------------------------------------------------------------------------------------------------------------------------+
|
CREATE TEMPORARY TABLE tmp_test1
SELECT ? AS prepared_stmt_arg, col_tmp1 # AS constant_col_alias
FROM tmp1
|
+---------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
+-------------------------+----------+
| prepared_stmt_arg | col_tmp1 |
+-------------------------+----------+
| prepared_stmt_arg_value | 1 |
+-------------------------+----------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> CALL test1('col_tmp2', 'tmp2');
+---------------------------------------------------------------------------------------------------------------------------------+
| @prepared_stmt |
+---------------------------------------------------------------------------------------------------------------------------------+
|
CREATE TEMPORARY TABLE tmp_test1
SELECT ? AS prepared_stmt_arg, col_tmp2 # AS constant_col_alias
FROM tmp2
|
+---------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
ERROR 1054 (42S22): Unknown column 'dev.tmp_test1.col_tmp1' in 'field list'
However, if you uncomment the column alias (remove the # just before AS constant_col_alias
), all works well. (You may need to scroll down to see Query OK.)
mysql> CALL test1('col_tmp1', 'tmp1');
+-------------------------------------------------------------------------------------------------------------------------------+
| @prepared_stmt |
+-------------------------------------------------------------------------------------------------------------------------------+
|
CREATE TEMPORARY TABLE tmp_test1
SELECT ? AS prepared_stmt_arg, col_tmp1 AS constant_col_alias
FROM tmp1
|
+-------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
+-------------------------+--------------------+
| prepared_stmt_arg | constant_col_alias |
+-------------------------+--------------------+
| prepared_stmt_arg_value | 1 |
+-------------------------+--------------------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> CALL test1('col_tmp2', 'tmp2');
+-------------------------------------------------------------------------------------------------------------------------------+
| @prepared_stmt |
+-------------------------------------------------------------------------------------------------------------------------------+
|
CREATE TEMPORARY TABLE tmp_test1
SELECT ? AS prepared_stmt_arg, col_tmp2 AS constant_col_alias
FROM tmp2
|
+-------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
+-------------------------+--------------------+
| prepared_stmt_arg | constant_col_alias |
+-------------------------+--------------------+
| prepared_stmt_arg_value | 2 |
+-------------------------+--------------------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Well it seems to be a bug or a feature (if you want) up to version 5.6.
See Bug #32868 Stored routines do not detect changes in meta-data.
Workaround: flush the stored routine cache by doing this:
CREATE OR REPLACE VIEWtmpview
AS SELECT 1;
Here is SQLFiddle demo MySql 5.1.X
Here is SQLFiddle demo MySql 5.5.X
If you comment out CREATE OR REPLACE VIEW
tmpviewAS SELECT 1
you'll get your error.
Here is SQLFiddle demo MySql 5.6.X shows that it's no longer a problem
SELECT *
use explicit column names instead.