您可以在一条语句中将值存储在用户定义的变量中,然后在另一条语句中引用它。这使您能够将值从一个语句传递到另一个语句。
用户变量被写成@
,其中变量名var_name
var_name
由字母数字字符组成,.
,_
,$
.如果将用户变量名作为字符串或标识符引用,则可以包含其他字符(例如,@“my-var”
,@“my-var”
,或@“my-var”
).
用户定义变量是特定于会话的。一个客户端定义的用户变量不能被其他客户端看到或使用。(例外:访问性能架构的用户user_variables_by_thread
表可以看到所有会话的所有用户变量。)当客户端退出时,该客户端会话的所有变量将自动释放。
用户变量名不区分大小写。名称的最大长度为64个字符。
设置用户定义变量的一种方法是发出集
声明:
设置@var_name=expr(@var_name=expr)……
用户变量可以从有限的一组数据类型中分配值:整数、十进制、浮点、二进制或非二进制字符串,或者零
价值。分配小数和实值不会保留值的精度或比例。非允许类型的值被转换为允许类型。例如,具有时间或空间数据类型的值被转换为二进制字符串。价值具有JSON
数据类型转换为字符串,其字符集为utf8mb4
和整理utf8mb4_bin
.
如果为用户变量分配了非二进制(字符)字符串值,则它具有与字符串相同的字符集和排序规则。用户变量的强制性是隐式的。(这与表列值的强制力相同。)
分配给用户变量的十六进制或位值被视为二进制字符串。若要将十六进制或位值作为数字分配给用户变量,请在数值上下文中使用它。例如,添加0或使用铸造(…无符号)
:
SET @v1 = X'41';SET @v2 = X'41'+0;SET @v3 = CAST(X'41' AS UNSIGNED);SELECT @v1, @v2, @v3;+------+------+------+ | @ v1 | @v2 | @v3 | +------+------+------+ | 65 | | 65年 | +------+------+------+ mysql >设置@v1 = b“1000001”;SET @v2 = b'1000001'+0;SET @v3 = CAST(b'1000001' AS UNSIGNED);SELECT @v1, @v2, @v3;+------+------+------+ | @ v1 | @v2 | @v3 | +------+------+------+ | 65 | | 65年 | +------+------+------+
如果在结果集中选择了用户变量的值,它将作为字符串返回给客户机。
如果引用一个未初始化的变量,则它的值为零
和字符串的类型。
在允许表达式的大多数上下文中都可以使用用户变量。这目前不包括显式需要文字值的上下文,例如限制
一个条款选择
声明中,或忽略
一个条款N
行加载数据
声明。
也可以在其他语句中为用户变量赋值集
.(此功能在MySQL 8.0中已弃用,将在后续版本中删除。)当以这种方式进行赋值时,赋值操作符必须是:=
而不是=
因为后者被视为比较运算符=
在声明中集
:
SET @t1=1, @t2=2, @t3:=4;SELECT @t1, @t2, @t3, @t4:= @t1+@t2+@t3;+------+------+------+--------------------+ | @ t1 | @t2 | @t3 | @t4: = @t1 + @t2 + @t3 | +------+------+------+--------------------+ | 1 | 2 | 4 | 7 | +------+------+------+--------------------+
一般来说,除了在集
语句中,永远不要给用户变量赋值,然后在同一语句中读取该值。例如,增加一个变量,这是可以的:
SET @a = @a + 1;
对于其他语句,例如选择
,您可能会得到您所期望的结果,但这并不保证。在下面的语句中,您可能认为MySQL计算@a
然后再做一个赋值操作:
SELECT @a, @a:=@a+1,…;
然而,涉及用户变量的表达式的求值顺序是未定义的。
给变量赋值并在相同的非变量中读取值的另一个问题集
语句中,变量的默认结果类型基于其在语句开始处的类型。下面的例子说明了这一点:
mysql >设置@a = '测试';SELECT @a,(@a:=20) FROMtbl_name;
对于这个选择
语句,MySQL报告客户端列1是一个字符串,并转换所有的访问@a
到字符串,即使@a被设置为第二行的数字。后选择
语句执行时,@a
被视为下一个语句的数字。
要避免这种行为带来的问题,要么不给同一个变量赋值,要么在单个语句中读取该变量的值,要么将该变量设置为0
,0.0
,或”
在使用它之前定义其类型。
在一个选择
语句,每个选择表达式仅在发送到客户机时计算。这意味着在a有
,集团
,或命令
子句中,引用在选择表达式列表中被赋值的变量时,则可以不工作如预期:
mysql> SELECT (@aa:=id) AS a, (@aa+3) AS b FROMtbl_nameb = 5;
的引用b
在有
子句引用所使用的选择列表中表达式的别名@aa
.这并没有像预期的那样工作:@aa
包含的值id
从上一个选定的行,而不是从当前行。
用户变量用于提供数据值。它们不能直接在SQL语句中作为标识符或标识符的一部分使用,例如在需要表或数据库名称的上下文中,或者作为保留字,例如选择
.即使变量被引号括起来,这也是正确的,如下例所示:
SELECT c1 FROM t;+——+ | c1 | +----+ | 0 | +----+ | 1 | +----+ 2行集(0.00秒)mysql >设置@col =“c1”;查询OK, 0 rows affected (0.00 sec) mysql> SELECT @col FROM t;+------+ | @ 上校 | +------+ | c1 | +------+ 1行组(0.00秒)mysql >选择“@col”从t;错误1054 (42S22): Unknown column '@col' in 'field list' mysql> SET @col = " ' c1 ' ";查询OK, 0 rows affected (0.00 sec) mysql> SELECT @col FROM t;+------+ | @ 上校 | +------+ | ` c1 ` | +------+ 1行集(0.00秒)
用户变量不能用于提供标识符,但这一原则的一个例外是,当您构造一个字符串以用作以后执行的预备语句时。在这种情况下,可以使用用户变量来提供语句的任何部分。下面的例子说明了如何做到这一点:
mysql> SET @c = "c1";查询OK, 0 rows affected (0.00 sec) mysql> SET @s = CONCAT("SELECT ", @c, " FROM t");查询OK, 0 rows affected (0.00 sec) mysql> PREPARE stmt FROM @s;查询OK, 0 rows affected (0.04 sec) Statement prepared mysql> EXECUTE stmt;+——+ | c1 | +----+ | 0 | +----+ | 1 | +----+ 2行集(0.00秒)mysql >释放准备支撑;查询OK, 0行受影响(0.00秒)
看到第13.5节“准备好的报表”,以查询更多资料。
类似的技术可以在应用程序中使用程序变量构造SQL语句,如使用PHP 5所示:
<?PHP $mysqli = new mysqli("localhost", "user", "pass", "test");if(mysqli_connect_errno()) die("Connection failed: %s\n", mysqli_connect_error());$坳=“c1”;$query = "SELECT $col FROM t";$ = $ mysqli结果- >查询(查询);而(行=结果美元- > fetch_assoc()){回声”< p > "。行美元(“$坳”)。" < / p > \ n”;}结果- > close (); $mysqli->close(); ?>
以这种方式组装SQL语句有时称为”动态SQL”.