Spec-Zone.ru › MySQL 9.2

11.4 Переменные, определенные пользователем

Вы можете сохранить значение в переменной, определенной пользователем, в одном операторе и обратиться к нему позже в другом операторе. Это позволяет передавать значения из одного оператора в другой.

Переменные пользователя записываются как @var_name, где имя переменной var_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 LINES оператора LOAD DATA.

В предыдущих версиях MySQL было возможно присвоить значение переменной пользователя в операторах, отличных от SET. Эта функциональность поддерживается в MySQL 9.2 для обратной совместимости, но может быть удалена в будущих выпусках 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.
https://docs.oracle.com/cd/E17952_01/mysql-9.2-en/user-variables.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API