Spec-Zone .ru
спецификации, руководства, описания, API

9.4. Определяемые пользователем Переменные

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

Пользовательские переменные пишутся как @var_name, где имя переменной var_name состоит из алфавитно-цифровых символов,".", "_", и"$". Пользовательское имя переменной может содержать другие символы, если Вы заключаете его в кавычки как строку или идентификатор (например, @'my-var', @"my-var", или @`my-var`).

Пользовательские имена переменной не являются чувствительными к регистру в MySQL 5.0 и.

Один способ установить определяемую пользователем переменную, выходя a SET оператор:

SET @var_name = expr [, @var_name = expr] ...

Для SET, также = или := может использоваться в качестве оператора присваивания.

Можно также присвоить значение пользовательской переменной в операторах кроме SET. В этом случае оператор присваивания должен быть := и нет = потому что последний обрабатывается как оператор сравнения = в не -SET операторы:

mysql> SET @t1=1, @t2=2, @t3:=4;mysql> SELECT @t1, @t2, @t3, @t4 := @t1+@t2+@t3;+------+------+------+--------------------+| @t1  | @t2  | @t3  | @t4 := @t1+@t2+@t3 |+------+------+------+--------------------+|    1 |    2 |    4 |                  7 | +------+------+------+--------------------+

Пользовательские переменные могут быть присвоены значение от ограниченного набора типов данных: целое число, десятичная, двоичная или недвоичная строка с плавающей точкой, или NULL значение. Присвоение десятичных и действительных значений не сохраняет точность или масштаб значения. Значение типа кроме одного из допустимых типов преобразовывается в допустимый тип. Например, значение, имеющее временный или пространственный тип данных, преобразовывается в двоичную строку.

Если пользовательская переменная присваивается недвоичное (символьное) строковое значение, у нее есть тот же самый набор символов и сопоставление как строка. coercibility пользовательских переменных неявен. (Это - тот же самый coercibility что касается значений столбца таблицы.)

Битовые значения, присвоенные пользовательским переменным, обрабатываются как двоичные строки. Чтобы присвоить немного значения как число к пользовательской переменной, использовать CAST() или +0:

mysql> SET @v1 = b'1000001';mysql> SET @v2 = CAST(b'1000001' AS UNSIGNED), @v3 = b'1000001'+0;mysql> SELECT @v1, @v2, @v3;+------+------+------+| @v1  | @v2  | @v3  |+------+------+------+| A    |   65 |   65 |+------+------+------+

Если значение пользовательской переменной выбирается в наборе результатов, оно возвращается клиенту как строка.

Если Вы обращаетесь к переменной, которая не была инициализирована, у нее есть значение NULL и тип строки.

Пользовательские переменные могут использоваться в большинстве контекстов, где выражения разрешаются. Это в настоящий момент не включает контексты, которые явно требуют литерального значения, такой как в LIMIT пункт a SELECT оператор, или IGNORE N LINES пункт a LOAD DATA оператор.

Как правило никогда недопустимо присваивать значение пользовательской переменной и читать значение в пределах того же самого оператора. Вы могли бы получить результаты, которые Вы ожидаете, но это не гарантируется. Порядок оценки для выражений, включающих пользовательские переменные, неопределен и может измениться основанный на элементах, содержавших в пределах данного оператора; кроме того, этот порядок, как гарантируют, не будет тем же самым между выпусками MySQL Server. В SELECT @a, @a:=@a+1, ..., Вы могли бы думать, что MySQL оценит @a сначала и затем делайте уроки вторые. Однако, изменяя оператор (например, добавляя a GROUP BY, HAVING, или ORDER BY пункт), может заставить MySQL выбирать план выполнения с различным порядком оценки.

Другая проблема с присвоением значения к переменной и чтению значения в пределах того же самого оператора - то, что тип результата значения по умолчанию переменной основан на ее типе в начале оператора. Следующий пример иллюстрирует это:

mysql> SET
        @a='test';mysql> SELECT @a,(@a:=20) FROM tbl_name;

Для этого SELECT оператор, MySQL сообщает клиенту, что столбец каждый - строка и преобразовывает все доступы @a к строкам, даже при том, что @a устанавливается в число для второй строки. После SELECT оператор выполняется, @a расценивается как число для следующего оператора.

Чтобы избежать проблем с этим поведением, или не присваивайте значение и читайте значение той же самой переменной в пределах единственного оператора, или иначе устанавливайте переменную в 0, 0.0, или '' определить его тип прежде, чем Вы будете использовать это.

В a SELECT оператор, каждое избранное выражение оценивается только когда отправлено клиенту. Это означает это в a HAVING, GROUP BY, или ORDER BY пункт, относясь к переменной, которая присваивается значение в избранном списке выражения, не работает как ожидалось:

mysql> SELECT (@aa:=id) AS a, (@aa+3) AS b FROM tbl_name HAVING b=5;

Ссылка на b в HAVING пункт относится к псевдониму для выражения в списке выборки, который использует @aa. Это не работает как ожидалось: @aa содержит значение id от предыдущей выбранной строки, не от текущей строки.

Пользовательские переменные предназначаются, чтобы обеспечить значения данных. Они не могут использоваться непосредственно в 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 preparedmysql> EXECUTE stmt;+----+| c1 |+----+|  0 |+----+|  1 |+----+2 rows in set (0.00 sec)mysql> DEALLOCATE PREPARE stmt;Query OK, 0 rows affected (0.00 sec)

См. Раздел 13.5, "Синтаксис SQL для Готовых Операторов", для получения дополнительной информации.

Подобный метод может использоваться в прикладных программах, чтобы создать 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".