0

我是 MySQL 新手,尝试编写一些 MySQL 存储过程并遇到一些我找不到修复的错误。

重现错误的简单存储过程

DELIMITER //
DROP PROCEDURE IF EXISTS testing;
CREATE PROCEDURE testing(sqlQuery varchar(100))
BEGIN
PREPARE stmt FROM sqlQuery;
EXECUTE stmt ;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;

我正在应用程序服务器上构建动态 sql 查询并将其作为参数发送到 MySQL 数据库服务器。

为简单起见,让我们考虑 sqlQuery contains SELECT * FROM Users

当我第一次在 MySQL Workbench 中执行存储过程时,我得到:

Error Code: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'sqlQuery; EXECUTE stmt ; DEALLOCATE PREPARE stmt; END' at line 5

当我第二次执行它时,我得到:

Error Code: 2014 Commands out of sync; you can't run this command now

我找不到这些错误背后的原因。有人可以提供一些信息吗?谢谢。


MySQL:8.0.19

MySQL 工作台:8.0.19

4

2 回答 2

2

MYSQL需要准备好的语句的用户变量

在存储程序上下文中准备的语句不能引用存储过程或函数参数或局部变量,因为它们在程序结束时超出范围,并且如果稍后在程序之外执行该语句将不可用。作为一种解决方法,请改为参考用户定义的变量,这些变量也具有会话范围。

所以你需要一个中间作业:

DROP PROCEDURE IF EXISTS testing;

DELIMITER //
CREATE PROCEDURE testing(sqlQuery varchar(100))
BEGIN
    SET @sql = sqlQuery;
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END //

DELIMITER ;

DB Fiddle 上的演示

于 2020-03-16T22:05:58.123 回答
1

您不能在存储过程中使用局部变量。您必须为准备好的语句使用用户变量。

局部变量范围和分辨率

因为局部变量仅在存储程序执行期间才在作用域内,所以在存储程序中创建的准备好的语句中不允许对它们的引用。准备好的语句作用域是当前会话,而不是存储的程序,因此该语句可以在程序结束后执行,此时变量将不再在作用域内。

因此,只需将参数重新分配给用户变量。

DELIMITER //
DROP PROCEDURE IF EXISTS testing;
CREATE PROCEDURE testing(sqlQuery varchar(100))
BEGIN
SET @a = sqlQuery;
PREPARE stmt FROM @a;
EXECUTE stmt ;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;

这应该工作

于 2020-03-16T22:10:36.743 回答