问题描述
根据 MysqL 8.0 弃用 notes,从 MysqL 9.0 开始,将弃用带有 DECLARE
(例如 DECLARE studentID INT
)的用户变量定义:
支持在除 SET
之外的语句中设置用户变量
在 MysqL 8.0.13 中已弃用。此功能可能会被删除
在 MysqL 9.0 中。
现在 MysqL 8.0.25 已经发出警告:
1287 在表达式中设置用户变量已被弃用,并将
在以后的版本中删除。考虑替代方案:SET variable=expression,...
或 SELECT expression(s) INTO variables(s)
。
因此,我想了解如何将 DECLARE
正确替换为 SET
。假设我声明了以下变量:
DECLARE cursor_studentID INT;
DECLARE done INT DEFAULT FALSE;
DECLARE cursor_i CURSOR FOR SELECT courseID FROM tblCoursesTocopy;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
现在我想让这些声明与 MysqL 9.0 兼容。在 DECLARE cursor_studentID INT;
的情况下,一切都相对明显:
DECLARE cursor_studentID INT; → SET @cursor_studentID;
真正的障碍是最后一种情况:
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
我不明白如何用基于 SET
的方法替换它。
解决方法
弃用警告不明确,容易被误解。
DECLARE
语法未被弃用。我认为发行说明的作者不认为这是一种“设置”变量的方法。诚然,它确实通过使用可选的 DEFAULT
子句为声明的变量设置了初始值。但我仍然将其解释为一种不被视为已弃用的声明。
不赞成在这样的表达式中将变量设置为“副作用”:
SELECT @row := @row+1,...
该技术是 MySQL 在 8.0 之前的版本中缺少 window functions 的常见解决方法。但它是非标准语法,通常容易出错且难以使用。既然 MySQL 支持标准 SQL 窗口函数和通用表表达式,您可以像在其他流行的 SQL 实现中编写查询一样编写查询。上面的例子是:
SELECT ROW_NUMBER() OVER (),...
:=
赋值的另一个用途是将查询选择列表中的表达式保存到用户定义的变量中。 MySQL 为这种用法提供了 SELECT ... INTO
syntax。这个已经支持很久了,在 8.0 版本之前。
我们还没有听到任何更改 DECLARE
语法的公告。这不需要改变。
回复您的评论:
您可以使用以下任一形式来代替 SELECT @myVar := somevalue ...
:
SELECT someValue INTO @myVar ...
SET @myVar = (SELECT someValue FROM ...);
请注意,后一种形式不允许您为每个查询设置多个变量。前者允许您像这样设置多个变量:
SELECT someValue,otherValue INTO @myVar1,@myVal2 ...
阅读我在上面链接到的关于 SELECT ... INTO
的文档。