Mysql碎片整理:存储程序

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 定义变量;语句结束分隔符;存储函数;存储过程;游标在存储过程和存储函数中的使用;触发器的定义;事件的创建。

定义变量

语法:

SET为定义变量的关键字,@a是变量的名字,说明变量需要以@开头,1是给变量赋的值。

SET @a = 1;

你可以这样

SET @a = (SELECT 某列名 FROM 某表 LIMIT 1);

注意一个变量只能存一个值。

与查询结果相结合还有一种语法,将查询到的某个结果存入到变量中:

SELECT 某列名 FROM 某表 LIMIT 1 INTO @b

此时@b变量会被自动创建赋值。

该语法可以同时给多个变量赋值

SELECT 列名1,列名2 FROM 某表 LIMIT 1 INTO @c,@d;

语句结束分隔符

通常我们每次只输入一个sql语句,以;结尾,按下回车后就会把该独立的语句传入到SQL服务器。

每个单独的sql可以用以下结尾

  1. ;
  2. \g
  3. \G

但当我们想连续输入k个sql语句时就需要重新定义语句结束分隔符了

delimiter $

就像这样:

mysql> delimiter $ 
mysql> SELECT * FROM t1 LIMIT 1; 
    -> SELECT * FROM t2 LIMIT 1; 
    -> SELECT * FROM t3 LIMIT 1; 
    -> $

服务器在执行的时候还是以;结尾的sql语句单独执行,但是我们可以做到输入时多条sql语句回车会并不会触发执行。

操作结束记得修改回来。

delimiter ;

存储函数

输入要有输出。

它像SQL语句中我们定义的一个函数,通过操作这个函数,我们可以得到相应的结果。

语法:
参数是选择性的,我们还需要指明函数返回的类型,然后就在BEGINEND的包裹中写正常的sql即可。

CREATE FUNCTION 存储函数名称([参数列表])
RETURNS 返回值类型
BEGIN
    RETURN 函数体内容
END

**例如:
我们定义一个函数,计算某门成绩的平均分**

delimiter $
CREATE FUNCTION avg_score(s VARCHAR(100))
RETURNS DOUBLE
BEGIN
RETURN (SELECT AVG(score) FROM student_score WHERE subject = s);
END$

使用:

调用函数名即可

delimiter ;
select avg_score('计算机网络');

查看定义的存储函数

SHOW CREATE FUNCTION 函数名

删除存储函数

DROP FUNCTION 函数名

【高级】像编程一样写函数体

变量:

  • 定义局部变量,并初始化

    • DECLARE 变量名 类型 DEFAULT 值;
  • 使用自定义变量,自定义变量可以通过SELECT @a;查询

    • SET @a = 10

逻辑语句:

  • if
IF 表达式 THEN
处理语句列表
[ELSEIF 表达式 THEN
处理语句列表]
... # 这里可以有多个ELSEIF语句
[ELSE 处理语句列表]
END IF;

循环语句:

  • while

如果满足给定的表达式,则执行处理语句,否则退出循环。

WHILE 表达式 DO
处理语句列表
END WHILE;
  • REPEAT

先执行处理语句,再判断表达式是否成立,如果成立则退出循环,否则继续执行处理语句。

REPEAT
处理语句列表
UNTIL 表达式 END REPEAT;
  • LOOP

在处理语句列表中:RETURN语句直接让函数结束就可以达到停止循环的效果

LOOP
    处理语句列表
END LOOP;

flag跳出

使用LEAVE跳到定义的flag:处。记得在END LOOP后面加上flag名字

flag:LOOP
    IF i > n THEN
        LEAVE flag;
    END IF;
END LOOP flag;

存储过程

执行这些语句即可,不用返回值。

语法:

CREATE PROCEDURE 存储过程名称([参数列表])
BEGIN
需要执行的语句
END

例如做一些插入的工作:

delimiter $
CREATE PROCEDURE t1_operation(
m1_value INT,
n1_value CHAR(1) 
) 
BEGIN 
INSERT INTO t1(m1, n1) VALUES(m1_value, n1_value); 
END $

调用存储过程

使用CALL语句来调用一个存储过程

CALL 存储过程([参数列表]);

例如调用上面那个t1_operation存储过程:

CALL t1_operation(1, 'a');

调用后就相当于执行了INSERT语句了。

查看某个存储过程

SHOW CREATE PROCEDURE 存储过程名称

删除存储过程

DROP PROCEDURE 存储过程名称

参数前缀

[IN | OUT | INOUT] 参数名 数据类型
引自小册 MySQL 是怎样使用的:从零蛋开始学习 MySQL
前缀 实际参数是否必须是变量 描述
IN 用于调用者向存储过程传递数据,如果IN参数在过程中被修改,调用者不可见。IN参数只能被用于读取
OUT 用于把存储过程运行过程中产生的数据赋值给OUT参数,存储过程执行结束后,调用者可以访问到OUT参数。
INOUT 综合INOUT的特点,既可以用于调用者向存储过程传递数据,也可以用于存放存储过程中产生的数据以供调用者使用。

游标

用途:方便访问多条记录的结果集

使用的地方:全部都在存储函数存储过程中!

就像这个样子就是多条记录的结果集,看到那个箭头没,游标就像箭头一样一行一行遍历

SELECT m, n FROM t1;

+------+------+
|  m  |  n  |
+------+------+
-> |    1 | a    |
   |    2 | b    |
   |    3 | c    |
+------+------+

创建游标

在存储函数或存储过程中创建游标

创建游标的语句一定要放在局部变量声明后头。

DECLARE 游标名称 CURSOR FOR 查询语句;

例如这个是存储过程的例子:

CREATE PROCEDURE cursor_demo()
BEGIN
DECLARE t1_record_cursor CURSOR FOR SELECT m, n FROM t1;
END

打开和关闭游标

在存储函数或存储过程中打开和关闭游标
  • 打开:OPEN 游标名称;
  • 关闭:CLOSE 游标名称;
CREATE PROCEDURE cursor_demo()
BEGIN
DECLARE t1_record_cursor CURSOR FOR SELECT m, n FROM t1;

OPEN t1_record_cursor;
CLOSE t1_record_cursor;
END

通过游标访问记录

在存储函数或存储过程中通过游标访问记录

在OPEN后,CLOSE前 访问记录

遍历一行:FETCH 游标名 INTO 变量1, 变量2, ... 变量n

CREATE PROCEDURE cursor_demo()
BEGIN
DECLARE t1_record_cursor CURSOR FOR SELECT m, n FROM t1;

OPEN t1_record_cursor;

FETCH t1_record_cursor INTO m_value, n_value;
SELECT m_value, n_value;

CLOSE t1_record_cursor;
END

指定游标对应记录的各列的值依次赋值给INTO后边的各个变量。

可以用事件+循环的方式遍历每行

事件:DECLARE CONTINUE HANDLER FOR NOT FOUND SET 表达式;

当遍历结束后,就会触发表达式,可以设置一个值作为判断条件。

# 初始化一个值
DECLARE not_done INT DEFAULT 1;
# 如果遍历结束后会让这个值设置为 0
DECLARE CONTINUE HANDLER FOR NOT FOUND SET not_done = 0;

---
# OPEN 打开游标
---

# 循环
flag: LOOP
    # 不断读取
    FETCH t1_record_cursor INTO m_value, n_value; 
    # 如果读取结束后会让not_done=0
    IF not_done = 0
        # 使用LEAVE 跳出循环
        THEN LEAVE flag;
    END IF; 
END LOOP flag;
---
# CLOSE 关闭游标

触发器 TRIGGER

使用场景:执行某些操作时,让 MySQL服务器自动执行一些额外的语句

例如:

  1. 在向t1表中插入记录之后自动把这条记录插入到t2表。
  2. 校验数据

创建触发器

  • {xxx|xxx} :必须在其中选择一个

这是一个例子,别着急往下看解释:

CREATE TRIGGER 触发器名 
{BEFORE|AFTER} 
{INSERT|DELETE|UPDATE}
ON 表名
FOR EACH ROW
BEGIN
    触发器内容
END

解释:

名称 含义
BEFORE 在具体的语句执行【之前】就开始执行触发器的内容
AFTER 在具体的语句执行【之后】才开始执行触发器的内容
INSERT 当操作语句是INSERT时触发,针对插入的内容
DELETE 当操作语句是DELETE时触发,针对被删除的内容
UPDATE 当操作语句是UPDATE时触发,针对被修改的内容

FOR EACH ROW BEGIN ... END:影响的每一条记录都执行我们自定义的触发器内容

所以是不是有 2 * 3 = 6 种触发器的方式。
  1. INSERT之前;之后
  2. delete之前;之后
  3. UPDATE之前;之后

新值旧值

在触发器内容中设置

什么是新值旧值

针对每一条受影响的记录,我们需要一种访问该记录中的内容的方式,MySQL提供了NEWOLD两个单词来分别代表新记录和旧记录。

  1. INSERT的操作就是新值,NEW表示的是待插入的记录,没有OLD
  2. DELETE的操作将值删除,只有OLD表示的是被删除前的内容
  3. UPDATE的操作,NEW表示修改后的记录,OLD表示修改前的记录

正式的来创建一个触发器

触发器的命名规范:bi -- BEFIRE INSERT ; t1 -- 表名
delimiter $ 
CREATE TRIGGER bi_t1
BEFORE INSERT ON t1
FOR EACH ROW
    BEGIN
        IF NEW.m1 < 1 THEN
            SET NEW.m1 = 1;
        ELSEIF NEW.m1 > 10 THEN
            SET NEW.m1 = 10;
        END IF;
    END $
delimiter ;

查看触发器

查看所有

SHOW TRIGGERS;

查看具体

SHOW CREATE TRIGGER 触发器名;

删除触发器

DROP TRIGGER 触发器名;

事件

使用场景:让 MySQL服务器在某个时间点或者每隔一段时间自动地执行一些语句

创建事件 EVENT

语法:

CREATE EVENT [IF NOT EXISTS] 事件名
ON SCHEDULE {AT 确定的时间点| EVERY 时间间隔段}
[ON COMPLETION [NOT] PRESERVE]
[ENABLE | DISABLE | DISABLE ON SLAVE]
[COMMENT '注释']
DO BEGIN
    执行语句;
END

解释:

  1. 第一行CREATE EVENT [IF NOT EXISTS] 事件名:如果不存在则创建一个事件,指定事件名
  2. 第二行ON SCHEDULE {AT 确定的时间点| EVERY 时间间隔段}:定义事件执行的时间和时间间隔
  3. 第三行ON COMPLETION [NOT] PRESERVE:事件完成时是否删除事件:NOT PRESERVE是不删除;PRESERVE是删除
  4. 第四行ENABLE | DISABLE | DISABLE ON SLAVE:ENABLE表示事件是开启的;DISABLE表示该事件是关闭的;

DISABLE ON SLAVE表示事件在从机中是关闭的。默认ENABLE即可

  1. 第五行COMMENT '注释':定义事件的注释
  2. 第六行DO BEGIN 执行语句 END:若单条语句则不需要用BEGINEND包围。

常用示例:

  1. 【单次定时插入】指定在某个时间AT 'yyyy-MM-dd hh:mm:ss';向表名插入一条记录。
CREATE EVENT 事件名 
ON SCHEDULE
AT '2019-09-04 15:48:54'
DO INSERT INTO 表名(xx, xx) VALUES(xx, xx);
  1. 【循环定时】从2023-02-04 00:00:00开始。每天的0点向表名插入一条记录。
CREATE EVENT 事件名
ON SCHEDULE
EVERY '1' DAY STARTS '2023-02-04 00:00:00'
DO INSERT INTO 表名(xx, xx) VALUES(xx, xx);

学习途径:Navicat

  1. 定义是做的事情(多行用BEGIN END 隔开)

image.png

  1. 计划是时间

image.png

  • CURRENT_TIMESTAMP表示的是当前的时间
  • INTERVAL是间隔,例如

image.png

表示当前时间往后再间隔1年。此时的SQL语句为

CREATE EVENT `Untitled`
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL '1' YEAR
DO BEGIN
INSERT INTO book (type) VALUES ('传记');
INSERT INTO book (type) VALUES ('传记');
END;

表示当前时间开始,每天都执行

image.png

CREATE EVENT `Untitled`
ON SCHEDULE
EVERY '1' DAY STARTS CURRENT_TIMESTAMP
DO BEGIN
INSERT INTO book (type) VALUES ('传记');
INSERT INTO book (type) VALUES ('传记');
END;

表示当前时间延后的一小时后开始,每天都执行

image.png

CREATE EVENT `Untitled`
ON SCHEDULE
EVERY '1' DAY STARTS CURRENT_TIMESTAMP + INTERVAL '1' HOUR
DO BEGIN
INSERT INTO book (type) VALUES ('传记');
INSERT INTO book (type) VALUES ('传记');
END;

从明天开始,每一小时执行一次,三天后结束

image.png

CREATE EVENT `Untitled`
ON SCHEDULE
EVERY '1' HOUR STARTS CURRENT_TIMESTAMP + INTERVAL '1' DAY
DO BEGIN
INSERT INTO book (type) VALUES ('传记');
INSERT INTO book (type) VALUES ('传记');
END;

开启关闭事件定义

SHOW VARIABLES like 'event%'; -- 若为OFF,则执行下列指令

-- 开启 
SET GLOBAL event_scheduler = ON;

-- 关闭
SET GLOBAL event_scheduler = OFF;

查看事件

查看所有事件

SHOW ENENT;

查看具体

SHOW CREATE EVENT 事件名;

删除事件

DROP EVENT 事件名;
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
1月前
|
存储 缓存 关系型数据库
MySQL的varchar水真的太深了——InnoDB记录存储结构
varchar(M) 能存多少个字符,为什么提示最大16383?innodb怎么知道varchar真正有多长?记录为NULL,innodb如何处理?某个列数据占用的字节数非常多怎么办?影响每行实际可用空间的因素有哪些?本篇围绕innodb默认行格式dynamic来说说原理。
828 6
MySQL的varchar水真的太深了——InnoDB记录存储结构
|
3月前
|
存储 缓存 关系型数据库
鱼和熊掌如何兼得?一文解析RDS数据库存储架构升级
阿里云RDS率先推出新型存储类型通用云盘,提供低延迟、低成本、高持久性的用户体验。
鱼和熊掌如何兼得?一文解析RDS数据库存储架构升级
|
3月前
|
存储 关系型数据库 MySQL
Linux C/C++ 开发(学习笔记八):Mysql数据库图片存储
Linux C/C++ 开发(学习笔记八):Mysql数据库图片存储
47 0
|
3月前
|
NoSQL 关系型数据库 MySQL
基于Python和mysql开发的智慧校园答题考试系统(源码+数据库+程序配置说明书+程序使用说明书)
基于Python和mysql开发的智慧校园答题考试系统(源码+数据库+程序配置说明书+程序使用说明书)
|
3月前
|
NoSQL 关系型数据库 MySQL
基于Python和mysql开发的BBS问答社区管理系统(源码+数据库+程序配置说明书+程序使用说明书)
基于Python和mysql开发的BBS问答社区管理系统(源码+数据库+程序配置说明书+程序使用说明书)
|
3月前
|
存储 关系型数据库 MySQL
Mysql 存储大数据量问题
Mysql 存储大数据量问题
88 1
|
2月前
|
存储 缓存 关系型数据库
Mysql专栏 - Linux底层交互和Raid存储架构
Mysql专栏 - Linux底层交互和Raid存储架构
77 0
|
3月前
|
存储 关系型数据库 MySQL
MySQL相关(番外篇)- innodb 逻辑存储结构
MySQL相关(番外篇)- innodb 逻辑存储结构
32 0
|
3月前
|
存储 SQL 关系型数据库
MySQL存储过程 if、case、while、loop、游标、变量、条件处理程序
MySQL存储过程 if、case、while、loop、游标、变量、条件处理程序
41 0
|
3月前
|
存储 自然语言处理 关系型数据库
👨‍💻如何使用MySQL存储Emoji表情,UTF-8和UTF-8MB4字符编码有何区别?
👨‍💻如何使用MySQL存储Emoji表情,UTF-8和UTF-8MB4字符编码有何区别?
93 1