#mysql #sql #common-table-expression #local-variables
#mysql #sql #общее-табличное-выражение #локальные переменные
Вопрос:
Люди говорят, что CTE — это представление, и вы не можете установить переменную в CTE. Но я успешно установил переменную @ttl в CTE, выполнив запрос ниже:
with CTE as (select @ttl:=(select sum(num) from test))
И когда я запускаю это, что я считал просто другим способом установки переменной, я получил сообщение об ошибке:
with CTE as (set @ttl=(select sum(num) from test))
Я очень смущен. Что именно выполнимо, а что нет с точки зрения установки переменной в CTE?
Комментарии:
1. Не могли бы вы сказать, почему вы пытаетесь установить переменную в предложении with? Показать больше того, что вы на самом деле пытаетесь сделать? Мне кажется очень вероятным, что вы получите хороший совет для лучшего подхода к тому, что это такое.
Ответ №1:
В скобках указан подзапрос; подзапросы всегда являются операторами 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:
Подзапрос — это оператор SELECT внутри другого оператора.
Обратите внимание, что mysql устарел устанавливать переменные где угодно, кроме как в инструкции SET, поэтому в будущей версии ожидайте, что даже ваш первый CTE выдаст ошибку.
https://dev.mysql.com/doc/refman/8.0/en/user-variables.html:
Предыдущие версии MySQL позволяли присваивать значение переменной пользователя в операторах, отличных от SET. Эта функциональность поддерживается в MySQL 8.0 для обеспечения обратной совместимости, но может быть удалена в будущей версии MySQL.
Ответ №2:
Добавление к ответу от @ysth, вы можете использовать INTO
для присвоения переменной выражения в списке выбора:
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, после того, как назначение побочного эффекта с :=
вызывает ошибку.