1. 变量分类
类型 | 语法 | 作用域 | 定义方式 | 示例 |
---|---|---|---|---|
用户变量 | @var_name |
当前会话(连接)有效 | 通过 set 或 select 直接赋值 |
set @age = 25; |
系统变量 | @@global.var_name @@session.var_name |
全局或当前会话 | 服务器预定义,通过 set 修改 |
set global max_connections=200; |
局部变量 | var_name (无 @ 符号) |
存储过程/函数的 begin...end 块内 |
在存储过程/函数中使用 declare 声明 |
declare total int default 0; |
2. 用户变量
特点
- 以
@
开头,无需声明,直接赋值即可使用。 - 作用域:当前会话(客户端连接),关闭连接后失效。
- 赋值方式
set @var = 1; -- 直接赋值
select @var := column from table; -- 通过查询赋值
select max(column) into @var from table; -- into 语法
- 示例:生成行号
set @row_num = 0;
select (@row_num := @row_num 1) as row_number, name
from users
order by name;
注意事项
- 变量类型动态决定,赋值后自动推断(如整数、字符串)。
-
避免在复杂查询中依赖赋值顺序,可能导致结果不稳定。
3. 系统变量
分类
-
全局变量(global):影响整个mysql服务器,需super权限修改。
-
会话变量(session):仅影响当前会话,每个新会话继承全局变量值。
常用操作
-- 查看全局变量
show global variables like 'wait_timeout';
select @@global.wait_timeout;
-- 查看会话变量
show session variables like 'sort_buffer_size';
select @@session.sort_buffer_size;
-- 修改全局变量(需权限)
set global max_connections = 500;
-- 修改会话变量
set session sql_mode = 'strict_trans_tables';
持久化配置
- 使用set persist使全局变量永久生效(mysql 8.0 ):
set persist max_connections = 500; -- 保存到配置文件
4. 局部变量
-
定义:在存储过程、函数或触发器中通过declare声明。
-
作用域:仅在begin…end块内有效。
-
示例:
delimiter //
create procedure calculate()
begin
declare total int default 0; -- 局部变量
set total = 10 20;
select total;
end //
delimiter ;
5. 关键区别
特性 | 用户变量 (@var) | 系统变量 (@@var) | 局部变量 (var) |
---|---|---|---|
前缀 | @ | @@ | 无 |
作用域 | 会话级 | 全局/会话级 | 存储过程/函数块内 |
声明方式 | 无需声明 | 服务器预定义 | declare显式声明 |
生命周期 | 会话结束销毁 | 服务器重启重置(全局) | 块结束销毁 |
6. 常见问题
- 用户变量与查询顺序
在单条sql中多次修改用户变量可能导致不可预测结果,因执行顺序依赖优化器。例如:
select @a := @a 1, id from table; -- 确保先初始化@a
建议预先通过set初始化变量。
2. 变量命名冲突
用户变量在会话内共享,避免在存储过程中使用同名变量造成干扰。
3. 数据类型
用户变量类型由赋值决定,可动态转换:
set @value = '100'; -- 字符串
set @value = @value 0; -- 转为整型
总结
-
用户变量:临时存储会话级数据,适用于行号生成、中间计算。
-
系统变量:配置服务器行为,区分全局和会话作用域。
-
局部变量:封装在存储过程中,保证逻辑隔离。