在MySQL/MariaDB中有好几种变量类型:用户自定义变量、系统变量、一般的临时变量(即本地变量,或称为局部变量)。

1.用户变量

用户变量是基于会话的,也是基于用户的,所以我觉得称之为会话变量更合适,但会话变量一般用来表示系统会话变量(后面会说明),所以还是称之为用户变量好了。

只有本用户才能引用自身的用户变量,其他用户无法引用,且当用户退出会话时,用户变量自动销毁。

用户变量使用"@"开头,用户变量可以直接赋值,无需事先声明。在引用未赋值的用户变量时,该变量值为null

有以下三种方式设置用户变量:

  1. set语句,此时可以使用"="或者":="操作符;
  2. select语句,此时只能使用":="格式赋值,因为除了set语句中,"="都会被视为比较操作符。;
  3. select ... into var_name from TABLE语句,此时要求select语句只能返回标量值,即单行数据。因此为了保险,select into var_name的时候,应尽量结合limit语句限制输出。
set @a1=1,@a2=3,@a3:=2;
select @a4:=@a1+@a3;
select 33,'abc' into @a5,@a6 from dual;

查看变量值可以使用select语句。

MariaDB [test]> select @a1,@a2,@a3,@a4,@a5,@a6,@a7;
+------+------+------+------+------+------+------+
| @a1 | @a2 | @a3 | @a4 | @a5 | @a6 | @a7 |
+------+------+------+------+------+------+------+
| 1 | 3 | 2 | 3 | 33 | abc | NULL |
+------+------+------+------+------+------+------+

在mariadb 10.2.6中,引入了一张系统架构表information_schema.USER_VARIABLES,该表中记录了当前用户当前会话定义的用户变量信息。该信息架构表在mysql中没有。

MariaDB [test]> SELECT * FROM information_schema.USER_VARIABLES;
+---------------+----------------+---------------+--------------------+
| VARIABLE_NAME | VARIABLE_VALUE | VARIABLE_TYPE | CHARACTER_SET_NAME |
+---------------+----------------+---------------+--------------------+
| a6 | abc | VARCHAR | utf8 |
| i | 2 | INT | utf8 |
| a5 | 33 | INT | utf8 |
| a1 | 1 | INT | utf8 |
| a4 | 3 | INT | utf8 |
| a2 | 3 | INT | utf8 |
| a3 | 2 | INT | utf8 |
+---------------+----------------+---------------+--------------------+

2.系统变量

在MySQL/mariadb中维护两种系统变量:全局系统变量和会话系统变量。系统变量是用来设置MySQL服务运行属性和状态的。

全局系统变量使用global或者"@@global."关键字来设置。会话系统变量使用session或者"@@session."关键字来设置,其中session可以替换为Local,它们是同义词。如果省略这些关键字,则默认为session系统变量。设置global系统变量要求具有super权限。

-- 设置全局系统变量
set global sort_buffer_size=32M;
set @@global.sort_buffer_size=32M;
-- 设置会话系统变量
set session sort_buffer_size=32M;
set @@session.sort_buffer_size=32M;
set sort_buffer_size=32M;
-- 查看全局系统变量值
select @@global.sort_buffer_size;
show global variables like "sort_buffer%";
-- 查看会话系统变量,不能使用select sort_buffer_size
select @@session.sort_buffer_size;
select @@sort_buffer_size;
show [session] variables like "sort_buffer%";
-- 一次性设置多个变量,包括会话变量、全局变量以及用户变量
SET @x = 1, SESSION sql_mode = '';
SET GLOBAL sort_buffer_size = 1000000, SESSION sort_buffer_size = 1000000;
SET @@global.sort_buffer_size = 1000000, @@local.sort_buffer_size = 1000000;
SET GLOBAL max_connections = 1000, sort_buffer_size = 1000000;

全局系统变量对全局有效,当有新的会话打开时,新会话会继承全局系统变量的值,所以设置全局系统变量之后新打开的会话都会继承设置后的值。设置全局系统变量对已经打开的连接无效,但是其他已经打开的连接可以查看到设置后的全局系统变量值。

系统变量按照是否允许在运行时修改,还分为动态变量和静态变量。能在运行过程中修改的变量称为动态变量,只能在数据库实例关闭状态下修改的变量称为静态变量或只读变量。动态变量使用set修改。如果在数据库实例运行状态下修改静态变量,则会给出错误。如:

set @@innodb_undo_tablespaces=3;
ERROR 1238 (HY000): Variable 'innodb_undo_tablespaces' is a read only variable

系统变量除了可以在运行中的环境下设置,还可以在配置文件中或者mysqld/mysqld_safe这样的命令行中设置,甚至mysql客户端命令行也可以传递。在配置文件中设置系统变量时,下划线或者短横线都允许,它们表示同一个意思。例如下面的两行配置是等价的:

innodb_file_per_table=1
innodb-file-per-table=1

3.局部变量

局部变量也称为本地变量,只能在begin...and语句块中生效。它不像用户变量,本地变量必须使用declare事先声明,所以declare也必须在begin...end中使用。

局部变量无论是声明还是调用的时候都不需要任何多余的符号(即不需要@符号),直接使用其名称var_name即可。

使用declare声明变量,可以一次性声明多个同类型的变量,需要时可有直接为其指定默认值,不指定时默认为null。

decalre var_name,... type [default value];

使用set为变量赋值。MySQL/mariadb中set支持一次性赋值多个变量。

在begin...end中的set是一般set语句的扩展版本,它既可以设置系统变量、用户变量,也可以设置此处的本地变量。

set var_name=expr,[var_name=expr1,...]

或者使用select...into语句从表中获取值来赋值给变量,但是这样的赋值行为要求表的返回结果必须是单列且单行的标量结果。例如下面的语句将col的列值赋值给var_name变量。

select col into var_name from table_name;

因为局部变量只能在begin...end中使用,所以此处使用存储过程的例子来演示。

DROP PROCEDURE IF EXISTS haha;
DELIMITER $$
CREATE PROCEDURE haha()
BEGIN
DECLARE a INT;
SET a=1;
SET @i:=2;
SELECT a,@i;
END$$
DELIMITER ; CALL haha();
a @i
------ --------
1 2

在MySQL中,begin...end只能定义在存储程序中,所以declare也只能定义在存储程序内。但在mariadb中,begin...end是允许定义在存储程序(存储函数,存储过程,触发器,事件)之外的,所以decalre也算是能够定义在存储程序之外吧。需要定义在存储程序之外时,使用 begin not atomic 关键字即可。例如:

delimiter $$
begin not atomic
declare a int;
set a=3;
select a;
end$$

3.1 declare锚定其他对象的数据类型

在mariadb 10.3中(注意版本号,目前10.3版本还在测试中),declare语句允许在存储程序中使用TYPE OFROW TYPE OF 关键字基于表或游标来锚定数据类型。在mysql中不支持数据类型的锚定功能。

例如:

DECLARE tmp TYPE OF t1.a; -- 基于表t1中的a列获取数据类型
DECLARE rec1 ROW TYPE OF t1; -- 锚定表t1中行数据类型
DECLARE rec2 ROW TYPE OF cur1; -- 基于游标cur1获取行数据类型

通过其他对象来锚定本地变量的数据类型时,如果对象的数据类型改变,则本地数据类型也随之改变。这在某些时候非常有利于维护存储程序。

在定义存储程序时,不会检查declare锚定的对象是否存在。但在调用存储程序时,会先检查锚定对象是否存在。

当declare语句的锚定是基于表对象(不是游标)时,在调用存储程序的瞬间就会检查锚定的表是否存在,然后立刻声明该变量。因此:

  • (1).带有锚定功能的decalre语句可以定义在存储程序的任意位置;
  • (2).在存储程序中删除锚定的表对象,或者修改了锚定的表结构,都不会改变存储程序调用时声明的变量类型;
  • (3).所有带锚定功能的declare都是在存储程序调用之初被赋值的。

当declare语句的锚定是基于游标对象时,变量的数据类型是在执行变量声明语句时才获取到的。数据类型仅只锚定一次,之后不再改变。如果游标中的ROW TYPE OF变量是定义在一个循环之中,则数据类型在循环的开头就已经获取,且之后的循环不再改变。

示例:

create table t1(a int,b char(20));
drop procedure if exists haha;
delimiter $$
create procedure haha()
begin
declare x type of t1.a;
set x=1;
select x;
end$$
delimiter ; call haha();

MariaDB/MySQL中的变量的更多相关文章

  1. Mysql中的变量

    Mysql中的变量众多(即运行的配置),如:事务相关的.连接相关的.查询优化类的等等. 变量的作用域: 1.临时作用域 session级别:即打开一个与mysql server会话的基础上的作用域,变 ...

  2. MySql中的变量定义

    根据mysql手册,mysql的变量分为两种:系统变量和用户变量.但是在实际使用中,还会遇到诸如局部变量.会话变量等概念.根据个人感觉,mysql变量大体可以分为四种类型: 一.局部变量. 局部变量一 ...

  3. MySql中的变量定义(转)

    根据mysql手册,mysql的变量分为两种:系统变量和用户变量.但是在实际使用中,还会遇到诸如局部变量.会话变量等概念.根据个人感觉,mysql变量大体可以分为四种类型: 一.局部变量. 局部变量一 ...

  4. MYSQL 中的变量

    1.用户自己定义变量 2.系统变量(全局变量,会话变量) ----------------------------------------------------------------------- ...

  5. Node.js和mybatis分别实现mysql中like变量模糊查询

    <!-- mybatis --> <where> <if test="varName != '' and varName != null" > ...

  6. mysql查询语句中用户变量的使用

    先上代码吧 SELECT `notice`.`id` , `notice`.`fid` , `notice`.`has_read` , `notice`.`notice_time` , `notice ...

  7. MySQL中变量的使用

    一.认识MySQL 中的变量 在MySQL中变量的绝大部分的用处都是在存储过程和存储函数中. 当然也可以抛开存储过程和存储函数来单独使用. 变量在MySQL中的运用和在编程语言中的运用大体相同 二.M ...

  8. mysql中变量

    mysql中的变量: mysql中,有两种变量形式: 普通变量: 不带“@”符号: 定义形式: declare  变量名  类型名   [default  默认值]: //普通变量必须先这样定义 赋值 ...

  9. MySQL中变量的定义和变量的赋值使用(转)

    说明:现在市面上定义变量的教程和书籍基本都放在存储过程上说明,但是存储过程上变量只能作用于begin...end块中,而普通的变量定义和使用都说的比较少,针对此类问题只能在官方文档中才能找到讲解. 前 ...

随机推荐

  1. Tomcat下使用C3P0配置JNDI数据源(在项目的META-INF目录下创建context.xml的文件)

    一.C3P0下载 C3P0下载地址:http://sourceforge.net/projects/c3p0/files/?source=navbar 下载完成之后得到一个压缩包

  2. Excel2010 日文显示乱码

  3. TCP/IP资料整理

    一.概念 1. TCP/IP常见帧格式 2. 详解网络嗅探工具的原理 二.API 1. Linux kernel tcp 连接建立详解——由listen系统调用的backlog参数引发的长篇大论

  4. 【Luogu1414】又是毕业季II(数论)

    [Luogu1414]又是毕业季II(数论) 题面 题目背景 "叮铃铃铃",随着高考最后一科结考铃声的敲响,三年青春时光顿时凝固于此刻.毕业的欣喜怎敌那离别的不舍,憧憬着未来仍毋忘 ...

  5. .NET微服务 容器化.NET应用架构指南(支持.NET Core2)

    介绍 企业通过使用容器,日益实现成本节约.解决部署问题并改进 DevOps 和生产操作. 通过创建 Azure 容器服务.Azure Service Fabric 等产品,同时与 Docker.Mes ...

  6. 论文笔记(7):Constrained Convolutional Neural Networks for Weakly Supervised Segmentation

    UC Berkeley的Deepak Pathak 使用了一个具有图像级别标记的训练数据来做弱监督学习.训练数据中只给出图像中包含某种物体,但是没有其位置信息和所包含的像素信息.该文章的方法将imag ...

  7. 【learning】莫比乌斯反演

    吐槽 额其实这个东西的话..好像缠着机房里面的dalao们给我讲过好多遍了然后.. 拖到现在才搞懂也是服了qwq(可能有个猪脑子) 感觉就是主要几条式子然后疯狂换元换着换着就化简运算了? 草稿纸杀手q ...

  8. python迭代和切片

    from collections import Iterable #切片************************ # #取一个list或tuple的部分元素是非常常见的操作 ,Python提供 ...

  9. hadoop-eclipse-plugin-2.x.x 插件编译

    在网上找的hadoop for eclipse 插件都不能用,决定自己去编译一个.Hadoop 提供了一个 Eclipse 插件以方便用户在 Eclipse 集成开发环境中使用 Hadoop,如管理 ...

  10. PAT乙级-1037. 在霍格沃茨找零钱(20)

    如果你是哈利·波特迷,你会知道魔法世界有它自己的货币系统 -- 就如海格告诉哈利的:"十七个银西可(Sickle)兑一个加隆(Galleon),二十九个纳特(Knut)兑一个西可,很容易.& ...