数据库学习笔记(十五)--变量与定义条件与处理程序


前言

  • 学习和使用数据库可以说是程序员必须具备能力,这里将更新关于MYSQL的使用讲解,大概应该会更新30篇+,涵盖入门、进阶、高级(一些原理分析);

  • 这一篇讲解变量与定义条件与处理程序 ,有点像记忆类的东西,因为内容有点多,而且不是curd,可以先记录下来,留个影响;

  • 虽然MYSQL命令很多,但是自己去多敲一点,到后面忘记了,查一下就可以回忆起来使用了;

  • 这一系列也是本人学习MYSQL做的笔记,也是为了方便后面忘记查询;

  • 参考资料:黑马、csdn和知乎博客;

  • 欢迎收藏 + 关注,本人将会持续更新后端和AI算法的学习笔记。

    文章目录

    • 变量与定义条件与处理程序
      • [1. 变量](#1. 变量)
        • [1.1 系统变量](#1.1 系统变量)
          • [1.1.1 系统变量分类](#1.1.1 系统变量分类)
          • [1.1.2 查看系统变量](#1.1.2 查看系统变量)
          • [1.1.3 补充:MySQL 8.0的新特性------全局变量的持久化](#1.1.3 补充:MySQL 8.0的新特性——全局变量的持久化)
        • [1.2 用户变量](#1.2 用户变量)
          • [1.2.1 用户变量分类](#1.2.1 用户变量分类)
          • [1.2.2 会话用户变量](#1.2.2 会话用户变量)
          • [1.2.3 局部变量](#1.2.3 局部变量)
          • [1.2.4 会话用户变量与局部变量对比](#1.2.4 会话用户变量与局部变量对比)
      • [2. 定义条件与处理程序](#2. 定义条件与处理程序)
        • [2.1 案例分析](#2.1 案例分析)
        • [2.2 定义条件](#2.2 定义条件)
        • [2.3 定义处理程序](#2.3 定义处理程序)
        • [2.4 案例解决](#2.4 案例解决)

变量与定义条件与处理程序

1. 变量

在MySQL数据库的存储过程和函数中,可以使用变量来存储查询或计算的中间结果数据,或者输出最终的结果数据。

在 MySQL 数据库中,变量分为 系统变量以及用户自定义变量

1.1 系统变量

1.1.1 系统变量分类

变量由系统定义,不是用户定义,属于服务器层面。启动MySQL服务,生成MySQL服务实例期间, MySQL将为MySQL服务器内存中的系统变量赋值,这些系统变量定义了当前MySQL服务实例的属性、特征。

系统变量分为全局系统变量 (需要添加global关键字)以及会话系统变量 (需要添加session关键字),有时也把全局系统变量简称为全局变量,有时也把会话系统变量称为local变量。如果不写,默认是会话级别。

每一个MySQL客户机成功连接MySQL服务器后,都会产生与之对应的会话。会话期间,MySQL服务实例 会在MySQL服务器内存中生成与该会话对应的会话系统变量,这些会话系统变量的初始值是全局系统变 量值的复制。如下图:

  • 全局系统变量针对于所有会话(连接)有效,但不能跨重启。
  • 会话系统变量仅针对于当前会话(连接)有效。会话期间,当前会话对某个会话系统变量值的修改,不会影响其他会话同一个会话系统变量的值。

👀 注意:

  • 在MySQL中有些系统变量只能是全局的,例如 max_connections 用于限制服务器的最大连接数;
  • 有些系统变量作用域既可以是全局又可以是会话,例如 character_set_client 用于设置客户端的字符集;
  • 有些系统变量的作用域只能是当前会话,例如 pseudo_thread_id 用于标记当前会话的 MySQL 连接 ID。
1.1.2 查看系统变量
  • 查看所有或部分系统变量

    mysql 复制代码
    #查看所有全局变量
    SHOW GLOBAL VARIABLES;
    
    #查看所有会话变量
    SHOW SESSION VARIABLES;
    #或
    SHOW VARIABLES;
    mysql 复制代码
    #查看满足条件得部分系统变量
    SHOW GLOBAL VARIABLES LIKE '%标识符%';
    
    #查看满足条件的部分会话变量
    SHOW SESSION VARIABLES LIKE '%标识符%'

    范例:

    mysql 复制代码
    SHOW GLOBAL VARIABLES LIKE 'admin_%';
  • 查看指定系统变量

作为 MySQL 编码规范,MySQL 中的系统变量以 两个"@" 开头,其中"@@global"仅用于标记全局系统变量,"@@session"仅用于标记会话系统变量。"@@"首先标记会话系统变量,如果会话系统变量不存在, 则标记全局系统变量。

mysql 复制代码
#查看指定的系统变量的值
SELECT @@global.变量名;

#查看指定的会话变量的值
SELECT @@session.变量名;
#或
SELECT @@变量名;
  • 修改系统变量的值

有些时候,数据库管理员需要修改系统变量的默认值,以便修改当前会话或者MySQL服务实例的属性、 特征。具体方法:

方式1:修改MySQL 配置文件 ,继而修改MySQL系统变量的值(该方法需要重启MySQL服务)

方式2:在MySQL服务运行期间,使用"set"命令重新设置系统变量的值

mysql 复制代码
#为某个系统变量赋值
#方式1:
SET @@global.变量名=值;
#方式2:
SET GLOBAL 变量名=值;

#为某个会话变量赋值
#方式1:
SET @@session.变量名=值;
#方式2:
SET SESSION 变量名=值

范例:

mysql 复制代码
SELECT @@global.autocommit;
SET GLOBAL autocommit=0;
mysql 复制代码
SELECT @@session.tx_isolation;
SET @@session.tx_isolation='read-uncommitted';
mysql 复制代码
SET GLOBAL max_connections = 1000;
SELECT @@global.max_connections;
1.1.3 补充:MySQL 8.0的新特性------全局变量的持久化

在MySQL数据库中,全局变量可以通过SET GLOBAL语句来设置。例如,设置服务器语句超时的限制,可以通过设置系统变量max_execution_time来实现:

mysql 复制代码
SET GLOBAL MAX_EXECUTION_TIME=2000;

使用SET GLOBAL语句设置的变量值只会 临时生效 。 数据库重启 后,服务器又会从MySQL配置文件中读取变量的默认值。 MySQL 8.0版本新增了 SET PERSIST 命令。例如,设置服务器的最大连接数为1000:

mysql 复制代码
SET PERSIST global max_connections = 1000;

MySQL会将该命令的配置保存到数据目录下的 mysqld-auto.cnf 文件中,下次启动时会读取该文件,用其中的配置来覆盖默认的配置文件。

举例:

查看全局变量max_connections的值,结果如下:

mysql 复制代码
mysql> show variables like '%max_connections%';
+------------------------+-------+
| Variable_name	| Value  |
+------------------------+-------+
| max_connections	| 151  |
| mysqlx_max_connections | 100|
+------------------------+-------+
2 rows in set, 1 warning (0.00 sec)

1.2 用户变量

1.2.1 用户变量分类

用户变量是用户自己定义的,作为 MySQL 编码规范,MySQL 中的用户变量以 一个"@" 开头。根据作用范围不同,又分为会话用户变量局部变量

  • 会话用户变量:作用域和会话变量一样,只对当前连接会话有效。
  • 局部变量:只在 BEGIN 和 END 语句块中有效。局部变量只能在存储过程和函数中使用。
1.2.2 会话用户变量
  • 变量的定义
mysql 复制代码
#方式1:"= 或 ":=
SET @用户变量=值
SET @用户变量:=值

#方式2:":=" 或 INTO关键字
SELECT @用户变量 :=表达式[FROM等子句];
SELECT 表达式 INTO @用户变量 [FROM等子句];
  • 查看自定义变量的值
mysql 复制代码
SELECT @用户变量;

范例:

mysql 复制代码
SET @n1 =1;
SET @n2 :=3;
SET @sum := @n1+@n2;
SELECT @sum;
mysql 复制代码
SELECT @num := COUNT(*) FROM emps;
SELECT @num;
mysql 复制代码
SELECT AVG(sal) INTO @avgsal FROM emps;
SELECT  @avgsal;
mysql 复制代码
#查看某个未定义的变量时,将得到NULL值,默认值
SELECT @maye;
1.2.3 局部变量

定义:可以使用 DECLARE 语句定义一个局部变量作用域:仅仅在定义它的 BEGIN ... END 中有效

位置:只能放在 BEGIN ... END 中,而且只能放在第一句

与SET区别之一:变量前面没有@

mysql 复制代码
BEGIN
	#声明局部变量
	DECLARE 变量1 数据类型 [DEFAULT 默认值];
	DECLARE 变量2,变量3,... 数据类型 [DEFAULT 默认值];
	
	#为局部变量赋值
	SET 变量1 = 值;
	SELECT 字段 INTO 变量2 [FROM 子句];
	
	#查看局部变量的值
	SELECT 变量1,变量2,变量3;
END	
1. 定义变量
mysql 复制代码
DECLARE 变量名 类型 [DEFAULT 值]; # 如果没有DEFAULT子句,初始值为NULL

范例:

mysql 复制代码
DECLARE num INT DEFAULT 100;
2.变量赋值

方式1:一般用于赋简单的值

mysql 复制代码
SET 变量=值;
SET 变量:=值;

方式2:一般用于赋表中的字段值

mysql 复制代码
SELECT 字段名或表达式 INTO 变量名 FROM 表;
3.使用变量
mysql 复制代码
SELECT 局部变量名;

**范例1:**声明局部变量,并分别赋值为emps表中empno为7369的ename和sal。

mysql 复制代码
CREATE PROCEDURE set_value() 
BEGIN
	DECLARE emp_name VARCHAR(25); 
	DECLARE em_sal DOUBLE(10,2);

	SELECT ename,sal INTO emp_name,emp_sal 
	FROM emps
	WHERE empno = 7369;

	SELECT emp_name,emp_sal; 
END;

**范例2:**声明两个变量,求和并打印 (分别使用会话用户变量、局部变量的方式实现)

mysql 复制代码
#方式1:使用用户变量
SET @m=1;
SET @n=2;
SET @sum = @m+@n;
SELECT @sum;
mysql 复制代码
#方式2:使用局部变量
CREATE PROCEDURE add_value()
BEGIN
	DECLARE m INT DEFAULT 1;
	DECLARE n INT DEFAULT 3;
	DECLARE sum INT;
	
	SET sum=m+n;
	SELECT sum;
END;

**范例3:**创建存储过程"diff_sal"查询某员工和他领导的薪资差距,并用IN参数eno接收员工编号,用OUT参数dif_sal输出薪资差距结果。

mysql 复制代码
CREATE PROCEDURE different_sal(IN eno INT,OUT dif_sal DOUBLE) 
BEGIN
	#声明局部变量
	DECLARE emp_sal,mgr_sal DOUBLE DEFAULT 0.0; 
	DECLARE mgr_no INT;

	SELECT sal INTO emp_sal FROM emps WHERE empno = eno; 	
	SELECT mgr INTO mgr_no FROM emps WHERE empno = eno; 
	SELECT sal INTO mgr_sal FROM emps WHERE empno = mgr_no;
	SET dif_sal = mgr_sal - emp_sal; 
END;

#调用
SET @emp_no = 102;
CALL different_salary(@emp_no,@diff_sal);

#查看
SELECT @diff_sal;
1.2.4 会话用户变量与局部变量对比
变量类型 作用域 定义位置 语法
会话用户变量 作用域当前会话 定义位置会话的任何地方 语法加@符号,不用指定类型
局部变量 定义它的BEGIN END中 BEGIN END的第一句话 一般不用加@,需要指定类型

2. 定义条件与处理程序

定义条件是事先定义程序执行过程中可能遇到的问题, 处理程序定义了在遇到问题时应当采取的处理方式,并且**保证存储过程或函数在遇到警告或错误时能继续执行。**这样可以增强存储程序处理问题的能力,避免程序异常停止运行。

📘 **说明:**定义条件和处理程序在存储过程、存储函数中都是支持的。

2.1 案例分析

**案例分析:**创建一个名称为"UpdateData"的存储过程。代码如下:

mysql 复制代码
CREATE PROCEDURE UpdateData() 
BEGIN
	SET @x = 1;
	UPDATE emps SET sal = NULL WHERE ename = 'WARD'; 
	SET @x = 2;
	UPDATE emps SET sal = 200 WHERE ename = 'WARD'; 
	SET @x = 3;
END ;

调用存储过程:

mysql 复制代码
mysql> CALL UpdateData();
ERROR 1048 (23000): Column 'sal' cannot be null

mysql> SELECT @x;
+------+
| @x	|
+------+
|	1 |
+------+
1 row in set (0.00 sec)

可以看到,此时@x变量的值为1。结合创建存储过程的SQL语句代码可以得出:在存储过程中未定义条件 和处理程序,且当存储过程中执行的SQL语句报错时,MySQL数据库会抛出错误,并退出当前SQL逻辑,不再向下继续执行。

2.2 定义条件

定义条件就是给MySQL中的错误码命名,这有助于存储的程序代码更清晰。它将一个错误名字和错误条件关联起来。这个名字可以随后被用在定义处理程序的 DECLARE HANDLER 语句中。

定义条件使用DECLARE语句,语法格式如下:

mysql 复制代码
DECLARE 错误名称 CONDITION FOR 错误码(或错误条件)

错误码的说明:

  • MySQL_error_codesqlstate_value 都可以表示MySQL的错误。
    • MySQL_error_code是数值类型错误代码。
    • sqlstate_value是长度为5的字符串类型错误代码。
  • 例如,在ERROR 1048 (23000)中,1048是MySQL_error_code,'23000'是sqlstate_value。
  • 例如,在ERROR 1146(42S02)中,1146是MySQL_error_code,'42S02'是sqlstate_value。

**范例1:**定义"Field_Not_Be_NULL"错误名与MySQL中违反非空约束的错误类型是"ERROR 1048 (23000)"对应。

mysql 复制代码
#使用MySQL_error_code
DECLARE Field_Not_Be_NULL CONDITION FOR 1048;

#使用sqlstate_value
DECLARE Field_Not_Be_NULL CONDITION FOR SQLSTATE '23000';

**范例2:**定义"ERROR 1148(42000)"错误,名称为command_not_allowed。

mysql 复制代码
#使用MySQL_error_code
DECLARE command_not_allowed CONDITION FOR 1148;

#使用sqlstate_value
DECLARE command_not_allowed CONDITION FOR SQLSTATE '42000';

2.3 定义处理程序

可以为SQL执行过程中发生的某种类型的错误定义特殊的处理程序。定义处理程序时,使用DECLARE语句 的语法如下:

mysql 复制代码
DECLARE 处理方式 HANDLER FOR 错误类型 处理语句;
  • 处理方式 :处理方式有3个取值:CONTINUE、EXIT、UNDO。
    • CONTINUE :表示遇到错误不处理,继续执行。
    • EXIT :表示遇到错误马上退出。
    • UNDO :表示遇到错误后撤回之前的操作。MySQL中暂时不支持这样的操作。
  • 错误类型: (即条件)可以有如下取值:
    • SQLSTATE '字符串错误码' :表示长度为5的sqlstate_value类型的错误代码;
    • MySQL_error_code :匹配数值类型错误代码;
    • 错误名称 :表示DECLARE ... CONDITION定义的错误条件名称。
    • SQLWARNING :匹配所有以01开头的SQLSTATE错误代码;
    • NOT FOUND :匹配所有以02开头的SQLSTATE错误代码;
    • SQLEXCEPTION :匹配所有没有被SQLWARNING或NOT FOUND捕获的SQLSTATE错误代码;

处理语句::如果出现上述条件之一,则采用对应的处理方式,并执行指定的处理语句。语句可以是 像" SET 变量 = 值 "这样的简单语句,也可以是使用 BEGIN ... END 编写的复合语句。

定义处理程序的几种方式,代码如下:

mysql 复制代码
#方法1:捕获sqlstate_value
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET @info = 'NO_SUCH_TABLE';

#方法2:捕获mysql_error_value
DECLARE CONTINUE HANDLER FOR 1146 SET @info = 'NO_SUCH_TABLE';

#方法3:先定义条件,再调用
DECLARE no_such_table CONDITION FOR 1146;
DECLARE CONTINUE HANDLER FOR NO_SUCH_TABLE SET @info = 'NO_SUCH_TABLE';

#方法4:使用SQLWARNING
DECLARE EXIT HANDLER FOR SQLWARNING SET @info = 'ERROR';

#方法5:使用NOT FOUND
DECLARE EXIT HANDLER FOR NOT FOUND SET @info = 'NO_SUCH_TABLE';

#方法6:使用SQLEXCEPTION
DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info = 'ERROR';

2.4 案例解决

在存储过程中,定义处理程序,捕获sqlstate_value值,当遇到MySQL_error_code值为1048时,执行

CONTINUE操作,并且将@proc_value的值设置为-1。

mysql 复制代码
CREATE PROCEDURE UpdateDataNoCondition() 
BEGIN
	#定义处理程序
	DECLARE CONTINUE HANDLER FOR 1048 SET @proc_value = -1;

	SET @x = 1;
	UPDATE emps SET sal = NULL WHERE ename = 'WARD'; 
	SET @x = 2;
	UPDATE emps SET sal = 200 WHERE ename = 'WARD'; 
	SET @x = 3;
END ;

调用过程:

mysql 复制代码
mysql> CALL UpdateDataWithCondition();
Query OK, 0 rows affected (0.01 sec)

mysql> SELECT @x,@proc_value;
+------+-------------+
| @x	| @proc_value |
+------+-------------+
|	3 |	-1 |
+------+-------------+
1 row in set (0.00 sec)
相关推荐
风象南6 小时前
我把大脑开源给了AI
人工智能·后端
Johny_Zhao8 小时前
OpenClaw安装部署教程
linux·人工智能·ai·云计算·系统运维·openclaw
NineData8 小时前
NineData 迁移评估功能正式上线
数据库·dba
飞哥数智坊8 小时前
我帮你读《一人公司(OPC)发展研究》
人工智能
tingshuo29178 小时前
S001 【模板】从前缀函数到KMP应用 字符串匹配 字符串周期
笔记
橙序员小站11 小时前
Agent Skill 是什么?一文讲透 Agent Skill 的设计与实现
前端·后端
怒放吧德德11 小时前
Netty 4.2 入门指南:从概念到第一个程序
java·后端·netty
冬奇Lab12 小时前
OpenClaw 源码精读(3):Agent 执行引擎——AI 如何「思考」并与真实世界交互?
人工智能·aigc
雨中飘荡的记忆12 小时前
大流量下库存扣减的数据库瓶颈:Redis分片缓存解决方案
java·redis·后端
NineData13 小时前
数据库迁移总踩坑?用 NineData 迁移评估,提前识别所有兼容性风险
数据库·程序员·云计算