MySQL 自定义变量(User-Defined Variable)详解与实战
在 MySQL 中,自定义变量(User-Defined Variable) 是一种会话级变量,用于在同一连接中临时保存数据。你可以在一个语句中保存结果,在另一个语句中再次使用,非常适合进行中间值传递或构建动态 SQL。
文章目录
- 一、什么是自定义变量?
- 1.1 自定义变量的定义与赋值方式
- 1.1.1 使用 SET 赋值
- 1.1.2 使用 SELECT ... INTO 赋值
- 1.1.3 使用 := 赋值(旧写法)
- 1.2 查询与查看变量
- 二、自定义变量常见应用
- 2.1 结果集编号(ROW_NUMBER 的替代方案)
- 2.2 动态 SQL 构建与执行
- 三、使用注意事项与最佳实践
- 四、相关阅读
一、什么是自定义变量?
自定义变量通常写作@var_name,它是基于会话的,即在会话期间有效,会话结束后自动销毁。
1.1 自定义变量的定义与赋值方式
自定义变量的创建有3种方式:
- 使用set语句和=或:=直接赋值。
- 在SQL查询中使用into关键字赋值。
- 在SQL查询中使用:=符号进行赋值(旧方法)。
1.1.1 使用 SET 赋值
第一种方式使用set语句直接赋值,下面的语句将变量@var_1的值设置为’abc’,赋值的符号可以是=或者:=
set @var_1='abc';
select @var_1;
1.1.2 使用 SELECT … INTO 赋值
第二种方式是在SQL查询的select 域使用into关键字将结果保存到变量中,例如下面的exam表中,将最高分和最低分分别保存到@max_score和@min_score变量中:
select student, score from exam;
select max(score),min(score) into @max_score,@min_score from exam;
1.1.3 使用 := 赋值(旧写法)
还有一种方式是在select域直接用@变量名:=字段值的方式对变量进行赋值,不过这种方式已经过时,将来可能会失效,格式如下:
select @max_score:=max(score),@min_score:=min(score) from exam;
使用这种方法可以看到有警告,可以通过show warings;语句进行查看,就是提示你此方法已过时,将来可能废弃:
show warnings;
变量创建并赋值之后,在整个会话周期内,你就可以把它当作一个常量使用了,下面使用@max_score的值查询exam表的记录:
select * from exam where score=@max_score;
1.2 查询与查看变量
创建自定义变量后,可以通过performance_schema.user_variables_by_thread查询已经定义了哪些变量和对应的值,直接查询结果如下:
select * from performance_schema.user_variables_by_thread;
二、自定义变量常见应用
除了临时的保存值,自定义变量还经常用在下面的场景中。
2.1 结果集编号(ROW_NUMBER 的替代方案)
在MySQL8.0之前没有窗口函数,因此经常使用自定义变量随记录自增的方式来进行编号,例如下面的按score降序的查询,我要对记录编号:
select student, score from exam order by score desc;
这里采用自定义变量@id和原结果集进行连接,设置初始值为0,并在原结果集每条记录上进行+1,从而实现编号的效果:
select @id:=@id+1 rownumber, t.* from
(select student, score from exam order by score desc) t,(select @id:=0) r;
当然,MySQL8.0之后,更推荐使用窗口函数来进行编号,其功能更加强大,写起来也比较简便,MySQL8.0窗口函数的用法可以参考下面的链接:
MySQL窗口函数(MySQL Window Functions)
2.2 动态 SQL 构建与执行
动态 SQL 指的是 在运行时动态生成并执行的 SQL 语句,而不是在代码中写死的固定 SQL,换句话说:SQL 的结构(表名、列名、WHERE 条件等)不是事先写好的,而是程序运行过程中根据情况条件拼出来的(例如购物网站的用户可以选择不同的筛选条件,SQL 的结构在运行前是无法确定的,我们要根据用户的选择动态拼接SQL)。
下面的例子是动态SQL的简单示例,我们将表名,SQL语句文本都放在变量中,完成SQL构建后再用prepare语句执行:
SET @table_name := 'exam';
SET @sql_text := CONCAT('SELECT * FROM ', @table_name, ' WHERE score > 90;'); -- 动态构建SQL文本PREPARE stmt FROM @sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
三、使用注意事项与最佳实践
下面是在使用自定义变量时的小建议:
- 自定义变量是会话级别,不同连接互不影响。
- 在同一 SELECT 中同时读取与修改变量,结果顺序不保证。
- 不要将用户输入直接拼接进动态 SQL,防止 SQL 注入。
- 变量默认类型为字符串,必要时可使用 CAST() 转换。
- 复杂逻辑推荐使用 局部变量(DECLARE)或窗口函数。
四、相关阅读
- MySQL窗口函数(MySQL Window Functions)
- MySQL Prepared语句(Prepared Statements)