11.4 Пользовательские переменные
Вы можете сохранить значение в пользовательской переменной в одном операторе и обратиться к нему позже в другом операторе. Это позволяет передавать значения из одного оператора в другой.
Пользовательские переменные записываются как @, где имя переменной var_namevar_name состоит из буквенно-цифровых символов, ., _ и $. Имя пользовательской переменной может содержать и другие символы, если вы заключаете его в кавычки как строку или идентификатор (например, @'my-var', @"my-var" или @`my-var`).
Пользовательские переменные специфичны для сессии. Пользовательская переменная, определенная одним клиентом, не видна и не может быть использована другими клиентами. (Исключение: пользователь с доступом к таблице Performance Schema user_variables_by_thread может видеть все пользовательские переменные для всех сессий.) Все переменные для данной сессии клиента автоматически освобождаются при выходе этого клиента.
Имена пользовательских переменных не чувствительны к регистру. Максимальная длина имен составляет 64 символа.
Один из способов установить пользовательскую переменную — выдать оператор SET:
SET @var_name = expr [, @var_name = expr] ...
Для SET в качестве оператора присваивания можно использовать либо =, либо :=.
Пользовательским переменным можно присвоить значение из ограниченного набора типов данных: целые, десятичные, с плавающей точкой, двоичные или недвоичные строки или значение NULL. При присваивании десятичных и вещественных значений точность и масштаб значения не сохраняются. Значение типа, отличного от одного из разрешенных типов, преобразуется в разрешенный тип. Например, значение, имеющее временной или пространственный тип данных, преобразуется в двоичную строку. Значение, имеющее тип данных JSON, преобразуется в строку с набором символов utf8mb4 и сортировкой utf8mb4_bin.
Если пользовательской переменной присваивается значение недвоичной (символьной) строки, то у неё такой же набор символов и сортировка, как у строки. Коэрцибильность пользовательских переменных неявная. (Это такая же коэрцибильность, как и для значений столбцов таблицы.)
Шестнадцатеричные или битовые значения, присваиваемые пользовательским переменным, обрабатываются как двоичные строки. Чтобы присвоить шестнадцатеричное или битовое значение как число пользовательской переменной, используйте его в числовом контексте. Например, добавьте 0 или используйте CAST(... AS UNSIGNED):
mysql> SET @v1 = X'41';
mysql> SET @v2 = X'41'+0;
mysql> SET @v3 = CAST(X'41' AS UNSIGNED);
mysql> SELECT @v1, @v2, @v3;
+------+------+------+
| @v1 | @v2 | @v3 |
+------+------+------+
| A | 65 | 65 |
+------+------+------+
mysql> SET @v1 = b'1000001';
mysql> SET @v2 = b'1000001'+0;
mysql> SET @v3 = CAST(b'1000001' AS UNSIGNED);
mysql> SELECT @v1, @v2, @v3;
+------+------+------+
| @v1 | @v2 | @v3 |
+------+------+------+
| A | 65 | 65 |
+------+------+------+
Если значение пользовательской переменной выбирается в наборе результатов, оно возвращается клиенту как строка.
Если вы ссылаетесь на переменную, которая не была инициализирована, она имеет значение NULL и тип строки.
Ссылка на пользовательскую переменную в подготовленном операторе определяет её тип при первом подготовлении оператора и сохраняет этот тип при каждом последующем выполнении оператора. Аналогично, тип пользовательской переменной, используемой в операторе внутри хранимой процедуры, определяется при первом вызове хранимой процедуры и сохраняется при каждом последующем вызове.
Пользовательские переменные могут использоваться в большинстве контекстов, где разрешены выражения. Это не включает контексты, которые явно требуют литерального значения, такие как в ключе LIMIT оператора SELECT или ключе IGNORE оператора N LINESLOAD DATA.
В предыдущих версиях MySQL было возможно присваивать значение пользовательской переменной в операторах, отличных от SET. Эта функциональность поддерживается в MySQL 8.4 для обратной совместимости, но может быть удалена в будущих выпусках MySQL.
При таком присваивании необходимо использовать := в качестве оператора присваивания; = рассматривается как оператор сравнения в операторах, отличных от SET.
Порядок вычисления выражений, включающих пользовательские переменные, не определен. Например, нет гарантии, что SELECT @a, @a:=@a+1 вычислит @a сначала, а затем выполнит присваивание.
Кроме того, тип результата по умолчанию для переменной основан на её типе в начале оператора. Это может иметь непредвиденные последствия, если переменная содержит значение одного типа в начале оператора, в котором ей также присваивается новое значение другого типа.
Чтобы избежать проблем с этим поведением, либо не присваивайте значение и не читайте значение одной и той же переменной в одном операторе, либо установите переменную в 0, 0.0 или '', чтобы определить её тип до использования.
HAVING, GROUP BY и ORDER BY, при ссылке на переменную, которой присвоено значение в списке выражений выборки, не работают так, как ожидается, потому что выражение вычисляется на клиенте и, таким образом, может использовать устаревшие значения столбцов из предыдущей строки.
Пользовательские переменные предназначены для предоставления значений данных. Они не могут быть использованы непосредственно в операторе SQL в качестве идентификатора или части идентификатора, например, в контекстах, где ожидается имя таблицы или базы данных, или как зарезервированное слово, например, SELECT. Это верно даже в том случае, если переменная заключена в кавычки, как показано в следующем примере:
mysql> SELECT c1 FROM t;
+----+
| c1 |
+----+
| 0 |
+----+
| 1 |
+----+
2 rows in set (0.00 sec)
mysql> SET @col = "c1";
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @col FROM t;
+------+
| @col |
+------+
| c1 |
+------+
1 row in set (0.00 sec)
mysql> SELECT `@col` FROM t;
ERROR 1054 (42S22): Unknown column '@col' in 'field list'
mysql> SET @col = "`c1`";
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @col FROM t;
+------+
| @col |
+------+
| `c1` |
+------+
1 row in set (0.00 sec)
Исключение из этого принципа, что пользовательские переменные не могут использоваться для предоставления идентификаторов, заключается в том, что вы создаёте строку для использования в качестве подготовленного оператора, который будет выполнен позже. В этом случае пользовательские переменные могут использоваться для предоставления любой части оператора. Следующий пример показывает, как это можно сделать:
mysql> SET @c = "c1";
Query OK, 0 rows affected (0.00 sec)
mysql> SET @s = CONCAT("SELECT ", @c, " FROM t");
Query OK, 0 rows affected (0.00 sec)
mysql> PREPARE stmt FROM @s;
Query OK, 0 rows affected (0.04 sec)
Statement prepared
mysql> EXECUTE stmt;
+----+
| c1 |
+----+
| 0 |
+----+
| 1 |
+----+
2 rows in set (0.00 sec)
mysql> DEALLOCATE PREPARE stmt;
Query OK, 0 rows affected (0.00 sec)
Дополнительную информацию см. в Разделе 15.5, «Подготовленные операторы».
Аналогичный метод может использоваться в прикладных программах для создания операторов SQL с использованием переменных программы, как показано здесь с использованием PHP 5:
<?php
$mysqli = new mysqli("localhost", "user", "pass", "test");
if( mysqli_connect_errno() )
die("Connection failed: %s\n", mysqli_connect_error());
$col = "c1";
$query = "SELECT $col FROM t";
$result = $mysqli->query($query);
while($row = $result->fetch_assoc())
{
echo "<p>" . $row["$col"] . "</p>\n";
}
$result->close();
$mysqli->close();
?>
Сборка оператора SQL таким образом иногда называется «динамическим SQL».
© 2025 Oracle
Licensed under the GPLv2 License.