MySQL 在 CTE 中设置一个变量:"select" 可以,但 "set" 不起作用

MySQL set a variable inside CTE: "select" is fine but "set" doesn't work

人们说 CTE 是一个视图,您不能在 CTE 中设置变量。 但是我在 CTE 中成功地设置了一个变量@ttl 运行宁下面的查询:

with CTE as (select @ttl:=(select sum(num) from test))

当我 运行 这个,我以为只是另一种设置变量的方法时,我得到了一个错误:

with CTE as (set @ttl=(select sum(num) from test))

我很困惑。在 CTE 中设置变量究竟什么是可行的,什么是不可行的?

括号里的是子查询;子查询总是 SELECT 语句。

https://dev.mysql.com/doc/refman/8.0/en/with.html:

with_clause:
    WITH [RECURSIVE]
        cte_name [(col_name [, col_name] ...)] AS (subquery)
        [, cte_name [(col_name [, col_name] ...)] AS (subquery)] ...

https://dev.mysql.com/doc/refman/8.0/en/subqueries.html:

A subquery is a SELECT statement within another statement.

请注意,mysql 已弃用在 SET 语句以外的任何地方设置变量,因此在未来的版本中,即使是您的第一个 CTE 也会出错。

https://dev.mysql.com/doc/refman/8.0/en/user-variables.html:

Previous releases of MySQL made it possible to assign a value to a user variable in statements other than SET. This functionality is supported in MySQL 8.0 for backward compatibility but is subject to removal in a future release of MySQL.

添加到@ysth 的答案中,您可以使用 INTO 将 select 列表中的表达式分配给变量:

mysql> insert into test set num=42;

mysql> with cte as (select sum(num) as num from test) 
       select num into @ttl from cte;

mysql> select @ttl;
+------+
| @ttl |
+------+
|   42 |
+------+

注意 INTO 必须在外部查询中。如果您尝试在子查询中使用它,则会出现此错误:

mysql> with cte as (select sum(num) into @ttl from test) 
       select * from cte;
ERROR 3954 (HY000): Misplaced INTO clause, INTO is not allowed inside subqueries, 
and must be placed at end of UNION clauses.

我假设 INTO 语法即使在 MySQL 的未来版本中也将继续合法,因为 := 的副作用赋值会导致错误。