定义变量
语法:
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
可以用以下结尾
;
\g
\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语句中我们定义的一个函数,通过操作这个函数,我们可以得到相应的结果。
语法:
参数是选择性的,我们还需要指明函数返回的类型,然后就在BEGIN
和END
的包裹中写正常的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 |
是 | 综合IN 和OUT 的特点,既可以用于调用者向存储过程传递数据,也可以用于存放存储过程中产生的数据以供调用者使用。 |
游标
用途:方便访问多条记录的结果集使用的地方:全部都在存储函数和存储过程中!
就像这个样子就是多条记录的结果集,看到那个箭头没,游标就像箭头一样一行一行遍历:
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
服务器自动执行一些额外的语句
例如:
- 在向
t1
表中插入记录之后自动把这条记录插入到t2
表。 - 校验数据
创建触发器
- {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 种触发器的方式。
INSERT
之前;之后delete
之前;之后UPDATE
之前;之后
新值旧值
在触发器内容中设置
什么是新值旧值
针对每一条受影响的记录,我们需要一种访问该记录中的内容的方式,MySQL
提供了NEW
和OLD
两个单词来分别代表新记录和旧记录。
INSERT
的操作就是新值,NEW
表示的是待插入的记录,没有OLD
DELETE
的操作将值删除,只有OLD
表示的是被删除前的内容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
解释:
- 第一行
CREATE EVENT [IF NOT EXISTS] 事件名
:如果不存在则创建一个事件,指定事件名 - 第二行
ON SCHEDULE {AT 确定的时间点| EVERY 时间间隔段}
:定义事件执行的时间和时间间隔 - 第三行
ON COMPLETION [NOT] PRESERVE
:事件完成时是否删除事件:NOT PRESERVE
是不删除;PRESERVE
是删除 - 第四行
ENABLE | DISABLE | DISABLE ON SLAVE
:ENABLE表示事件是开启的;DISABLE表示该事件是关闭的;
DISABLE ON SLAVE表示事件在从机中是关闭的。默认ENABLE即可
- 第五行
COMMENT '注释'
:定义事件的注释 - 第六行
DO BEGIN 执行语句 END
:若单条语句则不需要用BEGIN
和END
包围。
常用示例:
- 【单次定时插入】指定在某个时间
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);
- 【循环定时】从
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
- 定义是做的事情(多行用
BEGIN
END
隔开)
- 计划是时间
CURRENT_TIMESTAMP
表示的是当前的时间INTERVAL
是间隔,例如
表示当前时间往后再间隔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;
表示当前时间开始,每天都执行
CREATE EVENT `Untitled`
ON SCHEDULE
EVERY '1' DAY STARTS CURRENT_TIMESTAMP
DO BEGIN
INSERT INTO book (type) VALUES ('传记');
INSERT INTO book (type) VALUES ('传记');
END;
表示当前时间延后的一小时后开始,每天都执行
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;
从明天开始,每一小时执行一次,三天后结束
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 事件名;