diff --git a/user-defined-variables.md b/user-defined-variables.md index d5dee81a65b1f..29ba125e414a5 100644 --- a/user-defined-variables.md +++ b/user-defined-variables.md @@ -7,134 +7,177 @@ aliases: ['/docs/v3.1/user-defined-variables/','/docs/v3.1/reference/sql/languag # User-Defined Variables +This document describes the concept of user-defined variables in TiDB and the methods to set and read the user-defined variables. + > **Warning:** > > User-defined variables are still an experimental feature. It is **NOT** recommended that you use them in the production environment. -The format of the user-defined variables is `@var_name`. `@var_name` consists of alphanumeric characters, `_`, and `$`. The user-defined variables are case-insensitive. +The format of the user-defined variables is `@var_name`. The characters that compose `var_name` can be any characters that can compose an identifier, including the numbers `0-9`, the letters `a-zA-Z`, the underscore `_`, the dollar sign `$`, and the UTF-8 characters. In addition, it also includes the English period `.`. The user-defined variables are case-insensitive. + +The user-defined variables are session-specific, which means a user variable defined by one client connection cannot be seen or used by other client connections. + +## Set the user-defined variables -The user-defined variables are session specific, which means a user variable defined by one client cannot be seen or used by other clients. +You can use the `SET` statement to set a user-defined variable, and the syntax is `SET @var_name = expr [, @var_name = expr] ...;`. For example: -You can use the `SET` statement to set a user variable: +{{< copyable "sql" >}} ```sql -SET @var_name = expr [, @var_name = expr] ... +SET @favorite_db = 'TiDB'; ``` -or +{{< copyable "sql" >}} ```sql -SET @var_name := expr +SET @a = 'a', @b = 'b', @c = 'c'; ``` -For `SET`, you can use `=` or `:=` as the assignment operator. +For the assignment operator, you can also use `:=`. For example: -For example: +{{< copyable "sql" >}} ```sql -mysql> SET @a1=1, @a2=2, @a3:=4; -mysql> SELECT @a1, @a2, @t3, @a4 := @a1+@a2+@a3; -+------+------+------+--------------------+ -| @a1 | @a2 | @a3 | @a4 := @a1+@a2+@a3 | -+------+------+------+--------------------+ -| 1 | 2 | 4 | 7 | -+------+------+------+--------------------+ +SET @favorite_db := 'TiDB'; ``` -Hexadecimal or bit values assigned to user variables are treated as binary strings in TiDB. To assign a hexadecimal or bit value as a number, use it in numeric context. For example, add `0` or use `CAST(... AS UNSIGNED)`: +The content to the right of the assignment operator can be any valid expression. For example: + +{{< copyable "sql" >}} ```sql -mysql> SELECT @v1, @v2, @v3; +SET @c = @a + @b; +``` + +{{< copyable "sql" >}} + +```sql +set @c = b'1000001' + b'1000001'; +``` + +## Read the user-defined variables + +To read a user-defined variable, you can use the `SELECT` statement to query: + +{{< copyable "sql" >}} + +```sql +SELECT @a1, @a2, @a3 +``` + +``` +------+------+------+ -| @v1 | @v2 | @v3 | +| @a1 | @a2 | @a3 | +------+------+------+ -| A | 65 | 65 | +| 1 | 2 | 4 | +------+------+------+ -1 row in set (0.00 sec) +``` + +You can also assign values in the `SELECT` statement: + +```sql +SELECT @a1, @a2, @a3, @a4 := @a1+@a2+@a3; +``` + +``` ++------+------+------+--------------------+ +| @a1 | @a2 | @a3 | @a4 := @a1+@a2+@a3 | ++------+------+------+--------------------+ +| 1 | 2 | 4 | 7 | ++------+------+------+--------------------+ +``` -mysql> SET @v1 = b'1000001'; -Query OK, 0 rows affected (0.00 sec) +Before the variable `@a4` is modified or the connection is closed, its value is always `7`。 -mysql> SET @v2 = b'1000001'+0; -Query OK, 0 rows affected (0.00 sec) +If a hexadecimal literal or binary literal is used when setting the user-defined variable, TiDB will treat it as a binary string. If you want to set it to a number, you can manually add the `CAST` conversion, or use the numeric operator in the expression: -mysql> SET @v3 = CAST(b'1000001' AS UNSIGNED); -Query OK, 0 rows affected (0.00 sec) +{{< copyable "sql" >}} + +```sql +SET @v1 = b'1000001'; +SET @v2 = b'1000001'+0; +SET @v3 = CAST(b'1000001' AS UNSIGNED); +``` + +{{< copyable "sql" >}} + +```sql +SELECT @v1, @v2, @v3; +``` -mysql> SELECT @v1, @v2, @v3; +``` +------+------+------+ -| @v1 | @v2 | @v3 | +| @v1 | @v2 | @v3 | +------+------+------+ -| A | 65 | 65 | +| A | 65 | 65 | +------+------+------+ -1 row in set (0.00 sec) ``` If you refer to a user-defined variable that has not been initialized, it has a value of NULL and a type of string. +{{< copyable "sql" >}} + ```sql -mysql> select @not_exist; +SELECT @not_exist; +``` + +``` +------------+ | @not_exist | +------------+ -| NULL | +| NULL | +------------+ -1 row in set (0.00 sec) ``` -The user-defined variables cannot be used as an identifier in the SQL statement. For example: +In addition to using the `SELECT` statement to read the user-defined variables, another common usage is the `PREPARE` statement. For example: + +{{< copyable "sql" >}} ```sql -mysql> select * from t; -+------+ -| a | -+------+ -| 1 | -+------+ -1 row in set (0.00 sec) +SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse'; +PREPARE stmt FROM @s; +SET @a = 6; +SET @b = 8; +EXECUTE stmt USING @a, @b; +``` -mysql> SET @col = "a"; -Query OK, 0 rows affected (0.00 sec) +``` ++------------+ +| hypotenuse | ++------------+ +| 10 | ++------------+ +``` -mysql> SELECT @col FROM t; -+------+ -| @col | -+------+ -| a | -+------+ -1 row in set (0.00 sec) +The contents of the user-defined variables are not recognized as identifiers in the SQL statements. For example: -mysql> SELECT `@col` FROM t; -ERROR 1054 (42S22): Unknown column '@col' in 'field list' +{{< copyable "sql" >}} -mysql> SET @col = "`a`"; -Query OK, 0 rows affected (0.00 sec) +```sql +SELECT * from t; +``` -mysql> SELECT @col FROM t; -+------+ -| @col | -+------+ -| `a` | -+------+ -1 row in set (0.01 sec) +``` ++---+ +| a | ++---+ +| 1 | ++---+ ``` -An exception is that when you are constructing a string for use as a prepared statement to execute later: +{{< copyable "sql" >}} ```sql -mysql> PREPARE stmt FROM "SELECT @c FROM t"; -Query OK, 0 rows affected (0.00 sec) +SET @col = "`a`"; +SELECT @col FROM t; +``` -mysql> EXECUTE stmt; +``` +------+ -| @c | +| @col | +------+ -| a | +| `a` | +------+ -1 row in set (0.01 sec) - -mysql> DEALLOCATE PREPARE stmt; -Query OK, 0 rows affected (0.00 sec) ``` For more information, see [User-Defined Variables in MySQL](https://dev.mysql.com/doc/refman/5.7/en/user-variables.html).