[英]MySQL SELECT * fails on temporary table created by PREPARE using dynamic column and table names after first pass
MySQL 5.2, CentOS 6.4. 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. 当列名和表名更改为与第一次遍历不同的值时,MySQL SELECT *在由PREPARE使用动态列名和表名创建的临时表上失败。
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. 该过程最后的SELECT语句失败。 (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. 但是,如果取消注释列别名的注释(删除AS constant_col_alias
之前的#),则一切正常。 (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. 嗯,这似乎是5.6版之前的错误或功能(如果需要)。
See Bug #32868 Stored routines do not detect changes in meta-data. 请参见Bug#32868。存储的例程无法检测元数据中的更改。
Workaround: flush the stored routine cache by doing this: 解决方法:通过执行以下操作刷新存储的例程缓存:
CREATE OR REPLACE VIEWtmpview
AS SELECT 1; 创建或替换视图tmpview
作为选择1;
Here is SQLFiddle demo MySql 5.1.X 这是SQLFiddle演示MySql 5.1.X
Here is SQLFiddle demo MySql 5.5.X 这是SQLFiddle演示MySql 5.5.X
If you comment out CREATE OR REPLACE VIEW
tmpview AS SELECT 1
you'll get your error. 如果您注释掉CREATE OR REPLACE VIEW
tmpview AS SELECT 1
您将得到您的错误。
Here is SQLFiddle demo MySql 5.6.X shows that it's no longer a problem 这是SQLFiddle演示MySql 5.6.X,它不再是问题
SELECT *
use explicit column names instead. 不要使用SELECT *
改用显式列名。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.