MySQL 进阶笔记:用户 / 会话 / 全局 / 局部变量 + CASE 分支语法

  • 🏠 博客主页:小谢同学的小破站
  • ✍️ 本文由 小谢同学的小破站 原创,首发于 CSDN💻
  • ☕ Java学习专栏:java
  • 📗 MySQL专栏:MySQL
  • 🧩 数据结构与算法:Java 数据结构与算法
  • 🌐C语言专栏: C语言
  • 👍 欢迎点赞👍 收藏⭐ 留言📝,发现错误欢迎指正!
  • ✨ 脚踏实地,持续深耕,奔赴自己的目标✨
    -- -- -- -- -- 💫分割线💫----------

MySQL 进阶笔记:用户 / 会话 / 全局 / 局部变量 + CASE 分支语法:

  • [1. 四大变量](#1. 四大变量)
    • [1.1 系统变量](#1.1 系统变量)
    • [1.2 用户自定义变量](#1.2 用户自定义变量)
    • [1.3 局部变量](#1.3 局部变量)
  • [2. SQL编程](#2. SQL编程)
    • [2.1 IF语句](#2.1 IF语句)
    • [2.2 CASE语句](#2.2 CASE语句)

前言:

  这里是小谢同学的 MySQL 学习记录,整理全局、会话、局部变量以及 SQL 编程语法。笔记用于自我复盘巩固,有错误欢迎大家指出,专栏还有 Java、网络、C 语言系列笔记欢迎翻阅

1. 四大变量

变量类型 声明方式 作用域 生命周期 查看
系统变量 系统定义好的 全局/会话 服务器运行期间 @@global.xxx / @@session.xxx
用户自定义变量 @var 当前会话 会话断开即销毁 @var
局部变量 DECLARE 存储过程 / 函数内部 代码块结束即销毁 直接用变量名
1.1 系统变量

系统变量又分为:全局变量会话变量

全局变量(Global):对所有新的连接都生效,修改后已经存在的连接不受影响

会话变量(Session):只对当前连接有效,断开连接需要重新部署

例如:大楼统一规定上班时长、门禁规则,只要进这个大楼,所有人都要遵守这套规则。

  1. 修改global全局变量:可以形象的理解为修改的是公司制度
  • 新进来的员工才会收到新规则的约束
  • 而老员工是已经存在的会话不会立即生效
  • 当MySQL重新启动之后,全局变量会默认恢复(相当于大楼断电重启,临时修改的制度表作废)
  1. 会话变量(session) = 每个员工自己的个人专属设置
  • 每个客户端连接,相当于一个独立员工。
  • 例如员工在擦自己桌子时不会影响到别人,喝水同理
  • 修改会话变量只会对当前一对话生效,别的连接完全不受影响
  • 连接断开会直接销毁,设置全部消失`

设置与查看系统变量:

sql 复制代码
-- 查看所有系统变量
SHOW GLOBAL VARIABLES;
show SESSION VARIABLES;

-- 查看指定的系统变量采用模糊查询的形式
select @@GLOBAL.系统变量名;
select @@SESSION.系统变量名;

-- @@ 不带前缀默认查 session 级
SELECT @@autocommit;

-- 查询auto开头的全局变量与查看以char结尾的会话系统变量
SHOW GLOBAL VARIABLES LIKE 'auto%';
SHOW SESSION VARIABLES LIKE 'char%';
-- 修改(会话级别,当前会话生效)
SET SESSION autocommit = 0;

-- 修改全局
SET GLOBAL autocommit = 0;

1.2 用户自定义变量

用户自定义变量是由用户自己定义 的,会话级别的变量,使用@前缀作为标识 ,相当于当前会话的临时记事本;

复制方式分为两种:

  • 一种为=进行赋值,
  • 或者:=进行赋值(更推荐使用:=这样更加明确是赋值操作而不是判断相等)

使用SET进行赋值

sql 复制代码
-- 方式一:
SET @name := '张三';
SET @age = 18;
select @name,@age;

使用SELECT进行赋值

sql 复制代码
-- 方式二
select @count:= COUNT(*) from student;
select @count;

不需要声明变量的类型,赋值时会自行进行判断

没有赋值的变量值为null

作用域: 只在当前会话中有效


1.3 局部变量

局部变量这个概念和我们之前学习的C语言和Java中类似,只不过MySQL中局部变量是存在于存储过程或者函数内部声明的变量,内部使用DECLARE来标识

局部变量的使用与赋值:

sql 复制代码
DELIMITER //
CREATE PROCEDURE p1()
BEGIN
-- 声明
DECLARE x INT DEFAULT 0;
DECLARE name varchar(20);
SET x := 100;
SET name := '张三';
SELECT x,name;
END //
DELIMITER ;

CALL p1();

注意要点:

  1. DECLARE必须写在BEGIN...END块的前面
  2. 必须指定类型(强类型),用户自定义变量为弱类型
  3. 作用域:只在BEGIN ...END内部

2. SQL编程

2.1 IF语句

结构化查询语言(StructuredQueryLanguage)简称为SQL,是一种特殊的编程语言,其中SQL也包含条件判断 ,循环 等等功能;

IF语句:

核心语法:

sql 复制代码
IF 条件1 THEN
    -- 语句
ELSEIF 条件2 THEN
    -- 语句
ELSE
    -- 语句
END IF;

示例:根据小萌的期末成绩来判断成绩等级:

sql 复制代码
DELIMITER //
CREATE PROCEDURE p2(IN score INT)
BEGIN

 IF score >= 90 THEN
   SELECT '优秀';
 ELSEIF score >= 60 THEN
		SELECT '及格';
 ELSE
     SELECT '不及格';
 END IF ;
 
END //
DELIMITER ;

CALL p2(99);

注意点:

  • 与C和JAVA想必'LSEIIF是一个单词而不是ELSE IF
  • 结束条件为END IF(中间带有空格),如果没有结束条件,程序则不知道何时结束
    存储过程里的 IF 语句 vs 普通查询里的 IF(条件, 值1, 值2) 函数

2.2 CASE语句

多分支选择,比多层 IF 更清晰。有两种写法,且既能当语句用(存储过程里),也能当表达式用(SELECT 里)

第一种简单的写法:简单的值匹配

例如:小萌在点外卖,买一号商品为:果汁,2号商品为猪脚饭,3号商品为桂林米粉

sql 复制代码
DELIMITER //
CREATE PROCEDURE p3(IN id INT,OUT food varchar(20))
BEGIN
 CASE id
 WHEN 1 THEN 
     SET food := '果汁';
 WHEN 2 THEN 
     SET food := '猪脚饭';
 WHEN 3 THEN 
     SET food := '桂林米粉';
 END CASE;
END //
DELIMITER ;

CAll p3(1,@food);
SELECT @food;

第二种写法:搜索CASE

还是以成绩为例子:

sql 复制代码
DELIMITER //
CREATE PROCEDURE p4(IN score INT,OUT lever VARCHAR(20))
BEGIN
CASE 
	WHEN score>=90 AND score <=100 THEN
		SET lever := '优秀';
	WHEN score >=60 AND score <90 THEN
		SET lever := '及格';
	ELSE  
	  SET lever :='非法参数';
END CASE;
END //
DELIMITER ;

CALL p4(99,@lever);
SELECT @lever;

注意事项:

  • 表达式 用结尾是 END;当语句 用(存储过程里)结尾是 END CASE
  • WHEN 按顺序匹配,命中第一个就停止,所以条件顺序很重要
  • ELSE 可以省略,省略后如果都不匹配返回 NULL

经典面试题:行转列

我们首先准备一张表插入并插入数据:

sql 复制代码
-- 创建成绩表
CREATE TABLE score (
    id INT PRIMARY KEY AUTO_INCREMENT,
    student_name VARCHAR(20),
    subject VARCHAR(20),
    score INT
);

INSERT INTO score(student_name,subject,score) VALUES
('张三','语文',88),
('张三','数学',95),
('张三','英语',78),
('李四','语文',76),
('李四','数学',82),
('李四','英语',90);

目标效果:

student_name 语文 数学 英语
张三 88 95 78
李四 76 82 90

代码实现:

sql 复制代码
SELECT
    student_name,
    SUM(CASE WHEN subject = '语文' THEN score ELSE 0 END) AS `语文`,
    SUM(CASE WHEN subject = '数学' THEN score ELSE 0 END) AS `数学`,
    SUM(CASE WHEN subject = '英语' THEN score ELSE 0 END) AS `英语`
FROM score
GROUP BY student_name;

逻辑梳理:

我们需要查询的是每一个人的成绩

第一步:先执行 CASE WHEN,还没分组、没求和

MySQL 先一行一行扫描整张表,对每一行 都执行 3 个 CASE 判断。

此时到这里就拿到了张三的每一条分散的记录

第二步:GROUP BY student_name

GROUP BY student_name 告诉数据库:把名字相同的所有行,归为一组

⚠️ 坑点来了:分组之后,一组里面有多条数据,不能直接返回多条,必须压缩成 1 行

所以必须使用聚合函数 SUM() / MAX()

第三步:SUM () 聚合收拢,多行合并成一行


相关推荐
Z59981784142 分钟前
c#软件开发学习笔记--WPF(控件、样式)
笔记·学习·c#
蒲锘42 分钟前
Devops项目笔记阶段 7:Jenkins CI/CD 自动化部署
笔记·jenkins·devops
KhalilRuan43 分钟前
秋招笔记——汇总
笔记
xcLeigh1 小时前
把CPU、内存、网络流量同时丢给TimechoAI,做交叉分析
数据库·内存·时序数据库·cpu·网络流量·timechoai·交叉分析
不好听6131 小时前
外键的 ON DELETE 与 ON UPDATE:父子表如何联动
数据库
格林威1 小时前
C#高位深相机图像保存:12位16位图像保存方案,OpenCvSharp和Halcon实现
开发语言·人工智能·数码相机·计算机视觉·c#·视觉检测·工业相机
ZGG0031 小时前
底座 01:Agent 的 token 成本怎么砍——Redis 缓存实战
数据库·redis·缓存
小小龙学IT1 小时前
Qt Graphics View Framework(图形视图框架)深度解析:从 Scene/View/Item 到工业级 2D 场景
开发语言·数据库·qt
2601_966949651 小时前
Python 量化数据质量校验:如何确保股票历史日线数据不存在缺失交易日?
开发语言·人工智能·爬虫·python·量化策略·量化·quantdash