在使用存储过程根据配置动态生成表并返回包含该表中记录的结果集(SELECT)时,对该过程的第二次调用将生成不同的表结构,但不会返回任何记录,并且会报告以前的同名临时表中缺少列。
我用MariaDB 10.3和10.1.21尝试了此操作,并收到了相同的结果。在尝试了单个和多个子过程的多种变体之后,我将代码最小化以证明错误。
我还尝试在执行过程之后尝试使用带有COMMITS的某些事务控制,然后再尝试使用不同的参数启动过程,但是得到了相同的结果。
DROP PROCEDURE IF EXISTS CreateATable;
DELIMITER $$
CREATE PROCEDURE CreateATable( _TableType tinyint )
BEGIN
DROP TEMPORARY TABLE IF EXISTS aTable;
IF _TableType = 1 THEN
SET @SQL_Statement :=
CONCAT(
'CREATE TEMPORARY TABLE aTable (',
'the_id bigint, ',
'the_column varchar(100) ',
') engine=INNODB',
';');
ELSE
SET @SQL_Statement :=
CONCAT(
'CREATE TEMPORARY TABLE aTable (',
'the_id bigint, ',
'the_other_column varchar(100) ',
') engine=INNODB',
';');
END IF;
PREPARE stmtCreateTable FROM @SQL_Statement;
EXECUTE stmtCreateTable;
DEALLOCATE PREPARE stmtCreateTable;
SET @SQL_Statement := NULL;
END$$
DELIMITER ;
DROP PROCEDURE IF EXISTS GetATable;
DELIMITER $$
CREATE PROCEDURE GetATable()
BEGIN
CALL CreateATable( 1 );
SELECT * FROM aTable;
CALL CreateATable( 2 );
SELECT * FROM aTable;
END$$
DELIMITER ;
DROP PROCEDURE IF EXISTS GetATable2;
DELIMITER $$
CREATE PROCEDURE GetATable2(_TableType tinyint)
BEGIN
CALL CreateATable( _TableType );
SELECT * FROM aTable;
END$$
DELIMITER ;
/*
Test execution script starts here
*/
-- Just CALL Create for one and Select
CALL CreateATable( 1 );
DESCRIBE aTable;
SELECT * FROM aTable;
CALL CreateATable( 2 );
DESCRIBE aTable;
SELECT * FROM aTable;
-- -> no errors
-- now CALL procedure to Create and Select from two different temp tables
CALL GetATable();
-- -> no errors
-- now CALL procedure to CREATE AND SELECT from ONE temp table definition using a parameter to select
CALL GetATable2(1);
CALL GetATable2(2);
-- Error Code: 1054. Unknown column 'mySchema.aTable.the_column' in 'field list'
我希望可以将参数传递给存储过程以生成临时表,并返回该临时表的记录。即使我在同一会话上使用不同的参数多次调用同一过程。
实际结果是,当调用存储过程以生成具有不同表结构的临时表时,它返回此错误,抱怨先前在同一存储过程的调用中创建的临时表中缺少该列。
错误代码:1054。“字段列表”中的未知列“ mySchema.aTable.the_column”
我发现防止此错误的唯一方法是 一种。结束jdbc连接并结束服务器会话 b。重新编译调用堆栈中的存储过程之一
重新编译不可行。并且结束会话似乎是不合理的。 这似乎是一个缺陷。但是有兴趣寻找是否有某种方法可以使它工作。
答案 0 :(得分:0)
这似乎是一个错误,您可以通过MariaDB bugs database直接向MariaDB团队报告。
一种临时解决方案是在存储过程GetATable2
中使用准备好的语句(我在MariaDB 10.3.16上的测试中使用EXECUTE IMMEDIATE):
...
CREATE PROCEDURE `GetATable2`(`_TableType` TINYINT)
BEGIN
CALL CreateATable(`_TableType`);
-- SELECT * FROM `aTable`;
EXECUTE IMMEDIATE 'SELECT * FROM `aTable`';
END$$
...
请参见dbfiddle。