首页 > 数据库 > > 9.4 用户定义的变量
参考官方文档:
https://dev.mysql.com/doc/refman/5.7/en/user-variables.html
您可以在一个语句中将值存储在用户定义的变量中,稍后在另一个语句中引用它。 这使您可以将值从一个语句传递到另一个语句。
用户变量写作@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,可以使用=或:=作为赋值运算符。
您也可以在SET以外的语句中为用户变量赋值。 在这种情况下,赋值运算符必须是:=和not =,因为后者在非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值。 小数和实数值的赋值不会保留数值的精度或比例。 允许类型以外的类型的值被转换为允许类型。 例如,具有时间或空间数据类型的值被转换为二进制字符串。 将具有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和字符串类型。
用户变量可用于允许表达式的大多数情况下。 这当前不包括显式需要文字值的上下文,例如SELECT语句的LIMIT子句或LOAD DATA语句的IGNORE N LINES子句。
作为一般规则,除了在SET语句中,您不应该在同一语句中分配一个用户变量和读取值。 例如,要增加一个变量,这是ok的:
SET @a = @a + 1;
对于其他语句,如SELECT,您可能会得到您期望的结果,但这不能保证。 在下面的语句中,你可能会认为MySQL会先评估@a然后再执行一个任务:
SELECT @a, @a:=@a+1, ...;
但是,涉及用户变量的表达式的评估顺序未定义。
---顺序不能被保证
将值赋给变量并读取同一个非SET语句中的值的另一个问题是,变量的默认结果类型是基于语句开头的类型。 以下示例说明了这一点:
mysql> SET @a='test';
mysql> SELECT @a,(@a:=20) FROM tbl_name;
对于这个SELECT语句,MySQL会向客户端报告第一列是一个字符串,并将@a的所有访问都转换为字符串,即使@a被设置为第二行的数字。 执行SELECT语句后,@a被视为下一个语句的编号。
要避免此行为的问题,请不要将值分配给单个语句中的相同变量的值,或者在使用它之前将该变量设置为0,0.0或''以定义其类型。
在SELECT语句中,每个选择表达式仅在发送给客户端时才被评估。 这意味着在HAVING,GROUP BY或ORDER BY子句中,引用在选择表达式列表中指定值的变量不能按预期工作:
mysql> SELECT (@aa:=id) AS a, (@aa+3) AS b FROM tbl_name HAVING b=5;
HAVING子句中对b的引用指的是使用@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 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)
在应用程序中可以使用类似的技术来使用程序变量来构造SQL语句。
以这种方式组装SQL语句有时称为“动态SQL”。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69946831/viewspace-3123852/ ,如需转载,请注明出处,否则将追究法律责任。