在MySQL使用过程中,我们经常会使用到一些变量,这些变量可能是系统变量或者用户自定义变量。如当查询或者修改系统配置的时候,可以查询和修改系统变量。当然在进行批处理脚本的时候,用户可以自定义变量,来实现数据的重复使用。

本文主要介绍系统变量和用户自定义变量的详细使用。需要说明的是,本篇文章代码中被[]包含的内容表示可选的,而被|分隔的内容表示可选其一。

系统变量

前面也说了变量分为系统变量和用户自定义变量,那么接下来就分别介绍这两个变量。

系统变量是指系统定义的变量,它是mysql服务器层面的。

系统变量分类

系统变量分为全局变量和会话变量。

(1)查看系统中所有变量的语法如下所示:

1
shwo [global | session] variables;

(2)查看全局变量的语法如下所示:

1
show global variables;

(3)查看会话变量的语法如下所示:

1
show session variables;

(4)如果想查询满足指定条件的系统变量,可以使用like关键字来实现模糊匹配:

1
shwo [global | session] like '%变量名%';

(5)查看指定的系统变量的语法如下所示:

1
select @@[global.|session.]系统变量名称;

请注意globalsession关键字后面有一个.点号;
(6)开发者可以使用如下命令来给对应的变量赋值:

1
2
3
4
5
//方式1
set [global|session]系统变量名 =值;

//方式2
set @@[global.|session.]系统变量名=值;

在上面给变量赋值的时候请注意,当变量是全局变量则需要添加global关键字;是会话变量则需要添加session关键字,如果开发者不写,那么默认将是session级别的变量。另外可以发现在上面的例子中,全局变量里面使用了@@符号,注意用户自定义变量中只有一个@符号。

全局变量

全局变量作用域

MySQL服务每次启动时都会为所有的系统变量设置初始值。

当然开发者可以为系统变量赋值,然后针对所有会话(连接)有效,注意它可以跨连接,但是不能跨重启,当用户将系统重启后,那么MySQL服务器会再次为所有的系统变量设置初始值。

全局变量演示

接下来将通过一些例子来演示全局变量的相关操作。

(1)查看所有的全局变量:

1
show global variables;

(2)查看包含’tx’字符的变量:

1
2
3
4
5
6
7
8
mysql> show global variables like '%tx%';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
| tx_read_only | OFF |
+---------------+-----------------+
2 rows in set, 1 warning (0.00 sec)

(3)查看指定名称的系统变量的值,如查看事务默认自动提交设置:

1
2
3
4
5
6
7
mysql> select @@global.autocommit;
+---------------------+
| @@global.autocommit |
+---------------------+
| 1 |
+---------------------+
1 row in set (0.03 sec)

(4)为某个变量赋值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mysql> set global autocommit=1;
Query OK, 0 rows affected (0.00 sec)

mysql> select @@global.autocommit;
+---------------------+
| @@global.autocommit |
+---------------------+
| 1 |
+---------------------+
1 row in set (0.00 sec)

mysql> set @@global.autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> select @@global.autocommit;
+---------------------+
| @@global.autocommit |
+---------------------+
| 0 |
+---------------------+
1 row in set (0.00 sec)

会话变量

会话变量作用域

会话变量只对当前会话(连接)有效,注意它不能跨连接使用。会话变量是在连接创建时,由MySQL自动给当前会话设置的变量。

会话变量演示

接下来将通过一些例子来演示会话变量的相关操作。

(1)查看所有的会话变量:

1
show session variables;

(2)查看包含’char’字符的会话变量:

1
show session variables like '%char%';

(3)查看指定名称的会话变量的值:

1
2
3
4
5
6
7
8
9
-- 查看事务默认自动提交的设置
select @@autocommit;
select @@session.autocommit;

--查看事务的隔离级别
select @@tx_isolation;
select @@session.tx_isolation;
````
(4)为某个会话变量赋值:

set @@session.tx_isolation=’read-uncommitted’;
set @@tx_isolation=’read-committed’;
set session tx_isolation=’read-committed’;
set tx_isolation=’read-committed’;

1
2
3
4
5
6
7
8
9
10
11
12
13
# 用户自定义变量
用户自定义变量顾名思义就是用户自己定义的,而不是系统提供的。
### 自定义变量使用
自定义变量使用分为三个步骤:第一步,声明;第二步,赋值;第三步,使用。

用户自定义变量也分为两种:用户变量和局部变量。
### 用户变量
##### 用户变量作用域
用户变量仅针对当前会话(连接)有效,它不能跨连接使用,其作用域同会话变量。

用户变量可以在任何地方使用,不仅可以用在begin end里面,也可以用在begin end外面。
##### 用户变量使用
请注意用户变量在声明时必须初始化,然后才能被使用。开发者可以使用如下三种方式来实现在用户变量声明时并初始化:

– 方法1
set @变量名=值;

– 方法2
set @变量名:=值;

– 方法3
select @变量名:=值;

1
2
3
前面在介绍全局变量的时候就说过,全局变量使用了两个`@`符号,而此处的用户变量则使用一个`@`符号,同时set中=号前面的冒号是可选的,而select中=号前面的冒号是必须的,不能缺少。
##### 用户变量赋值
用户变量赋值其实就是更新变量的值,它存在如下两种方式:

–方式1:方式同用户变量使用
set @变量名=值;
set @变量名:=值;
select @变量名:=值;

–方式2:使用select into语句
select 字段 into @变量名 from 表;

1
2
3
4
##### 用户变量演示
接下来通过一个综合的案例来演示用户变量:

(1)使用set方式来创建变量并初始化:

set @username = ‘envy’;

1
(2)使用select into方式来创建变量并初始化:

select ‘hellobook’ into @hello;
select count(*) into @empcount from employees;

1
(3)使用`select :=`方式来创建变量:

select @first_name:=’envy’,@email:=‘envybook@qq.com‘;

1
(4)使用变量:

insert into employees(first_name,email)values(@first_name,@email);

1
2
3
4
5
6
7
8
9
### 局部变量
##### 局部变量作用域
declare关键字用于定义局部变量,开发者可以在存储过程和函数中,通过使用declare关键字在begin end中定义变量,且在语句之前,注意可以重复定义多个变量。

declare变量的作用范围和编程中常用的范围非常类似,这里一般是在对应的begin和end之间,如果变量在end之后,那么这个变量就失效了,因为作用域结束了。
##### 局部变量使用
局部变量的使用和前面用户变量非常相似,都是先声明,后赋值,最后是再使用的原则。

第一步,声明。声明的语法如下所示:

declare 变量名 变量类型;
declare 变量名 变量类型 [default 默认值];

1
2

第二步,赋值。赋值的语法如下所示:

/方式1/
set 局部变量名=值;
set 局部变量名:=值;
select 局部变量名:=值;

/方式2:使用select into语句/
select 字段 into 局部变量名 from 表;

1
2
3
可以看到,局部变量前面是没有`@`符号的。

第三步,使用。使用的语法如下所示:

select 局部变量名;

1
2
3
4
##### 局部变量演示
接下来通过一个综合的案例来演示局部变量:

(1)创建book1表:

drop table if exists book1;
create table book1(a int primary key,b int);

1
(2)声明一个脚本,请注意声明脚本的结束符为`$$`:

delimiter $$
drop procedure if exists proc1;
create procedure proc1()
begin
/声明一个局部变量/
declare v_a int;

select ifnull(max(a),0)+1 into v_a from book1;
select @v_b:=v_a*2;
insert into book1(a,b) select v_a,@v_b;
end $$

/声明脚本的结束符为;/
delimiter;

/调用存储过程/
call proc1();

/查看结果/
select * from book1;

1
2
3
4
5
6
7
可以上面使用到了存储过程,关于存储过程会在后续文章中进行学习。
### delimiter关键字
在写SQL的时候,MySQL如何判断SQL已经结束?或者说需要去执行?当然需要一个结束符,当MySQL看到这个结束符的时候,就说明前面的语句就需要执行,你知道的在MySQL中默认以分号作为结束符。

当开发在创建存储过程或者自定义函数的时候,写了很长的SQL,且里面都使用了分号,但是我们却希望这个SQL语句是一个整体,需要一起执行,此时就希望分号不再是结束符了,可以使用delimiter关键字来自定义结束符。

delimiter关键字的用法如下所示:

delimiter 分隔符

1
接下来就将局部变量演示这个例子进行执行,执行结果如下所示:

mysql> drop table if exists book1;
Query OK, 0 rows affected (0.01 sec)

mysql> create table book1(a int primary key,b int);
Query OK, 0 rows affected (0.01 sec)

mysql> delimiter $$
mysql> drop procedure if exists proc1;
-> create procedure proc1()
-> begin
-> declare v_a int;
->
-> select ifnull(max(a),0)+1 into v_a from book1;
-> select @v_b:=v_a*2;
-> insert into book1(a,b) select v_a,@v_b;
-> end $$
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> delimiter;
mysql>
mysql> call proc1();
+————-+
| @v_b:=v_a*2 |
+————-+
| 2 |
+————-+
1 row in set (0.00 sec)

Query OK, 1 row affected (0.01 sec)

mysql> select * from book1;
+—+——+
| a | b |
+—+——+
| 1 | 2 |
+—+——+
1 row in set (0.00 sec)

```

用户变量和局部变量对比

接下来对前面所介绍的2种变量进行对比和总结

变量类型 作用域 定义位置 语法
用户变量 当前会话 会话的任意位置 添加@符号,不用指定类型
局部变量 定义在它的begin和end之间 begin end中的第一句话 不加@符号,但是必须指定类型

文章总结

本篇文章学习了系统变量和用户自定义变量,其中系统变量又可以分为全局变量和会话变量;用户自定义变量分为用户变量和局部变量。

系统变量可以设置系统的一些配置信息,数据库重启之后配置信息将会被还原;会话变量可以设置当前会话的一些配置信息,这些配置信息仅对当前会话起效;开发者可以使用declare来创建局部变量,局部变量常用于存储过程和函数的创建中。

全局变量对整个系统有效、会话变量作用于当前会话、用户变量作用于当前会话、局部变量作用于begin and之间。同时全局变量使用了@@,用户变量使用了@,而局部变量没有@符号。开发者还可以使用delimiter关键字来声明脚本的结束符,这个在某些场合下还是非常有用的。