gpt4 book ai didi

MySQL SELECT * 在第一次通过后使用动态列和表名在 PREPARE 创建的临时表上失败

转载 作者:行者123 更新时间:2023-11-29 00:26:58 33 4
gpt4 key购买 nike

MySQL 5.2、CentOS 6.4。

当列名和表名更改为与第一次通过时不同的值时,MySQL SELECT * 在第一次通过后使用动态列名和表名在 PREPARE 创建的临时表上失败。

解决方法是使用每次传递都保持相同的列别名。

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 ;

过程最后的 SELECT 语句失败。 (您可能需要向下滚动才能看到错误消息。)

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'

但是,如果您取消对列别名的注释(删除 AS constant_col_alias 之前的 #),则一切正常。 (您可能需要向下滚动才能看到查询正常。)

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)

最佳答案

好吧,这似乎是 5.6 版之前的错误或功能(如果你愿意的话)。

参见 Bug #32868 Stored routines do not detect changes in meta-data.

Workaround: flush the stored routine cache by doing this:
CREATE OR REPLACE VIEW tmpview AS SELECT 1;

这是 SQLFiddle 演示 MySql 5.1.X
这是 SQLFiddle 演示 MySql 5.5.X

如果你注释掉 CREATE OR REPLACE VIEWtmpviewAS SELECT 1 你会得到你的错误。

这是 SQLFiddle demo MySql 5.6.X 说明不再是问题


现在您至少可以选择以下选项:

  1. 不要使用 SELECT *,而是使用明确的列名。
  2. 使用建议的解决方法
  3. 升级到 5.6.X

关于MySQL SELECT * 在第一次通过后使用动态列和表名在 PREPARE 创建的临时表上失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18434035/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com