课程 › 第 16 章 › 实验四
第 16 章 · 实验四 · 在第六节之后

查看、修改、删除事件

查看实验三的事件,修改事件的周期、名称和注释,暂停和恢复事件,最后运行例题 6,再删除全部事件。

环 境

MySQL 8.0 和 MySQL Workbench,机房电脑已装好。所有语句在 Workbench 的 SQL 编辑区中执行。

执 行

Ctrl+Enter 执行光标所在的一句,Ctrl+Shift+Enter 执行全部。Mac 上把 Ctrl 换成 ⌘。

注 意

输入法切到英文。表名、字段名不加引号,字符串值才用单引号。

本次实验的顺序 后一个实验用到前一个的结果

  1. 实验 4-1查看全部事件
  2. 实验 4-2查看一个事件
  3. 实验 4-3修改事件
  4. 实验 4-4暂停与恢复
  5. 实验 4-5例题 6
第一步

数据准备(必做)

重建 teaching 库的五张表,打开事件调度器,建立 tb_one 表和实验三的 event_name4、event_name5。

整段复制,全部执行下载 .sql
-- 第 16 章实验四数据:五张表、tb_one 表和实验三建立的 event_name4、event_name5
-- 整段执行一次即可,想从头再做时重新执行。
CREATE DATABASE IF NOT EXISTS teaching DEFAULT CHARACTER SET utf8mb4;
USE teaching;

-- 删除本章实验建立的事件、存储过程和表,表上的触发器随表一起删除
DROP EVENT IF EXISTS event_name1;
DROP EVENT IF EXISTS event_name2;
DROP EVENT IF EXISTS event_name3;
DROP EVENT IF EXISTS event_name4;
DROP EVENT IF EXISTS name4;
DROP EVENT IF EXISTS event_name5;
DROP EVENT IF EXISTS event_name6;
DROP PROCEDURE IF EXISTS pro_score;
DROP TABLE IF EXISTS update_s_log, tb_one, week_score, t_demo;

-- 删除旧的表。先暂时关闭外键检查,库里有别的表引用它们时也能删除
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS sc, tc, avgsal, classroom, s, c, t;
SET FOREIGN_KEY_CHECKS = 1;

-- 课程表
CREATE TABLE c (
  cno CHAR(4) NOT NULL,
  cn VARCHAR(30) NOT NULL,
  ct INT,
  PRIMARY KEY (cno)
);
-- 学生表
CREATE TABLE s (
  sno CHAR(4) NOT NULL,
  sn VARCHAR(20) NOT NULL,
  sex CHAR(2),
  age INT,
  maj VARCHAR(30),
  dept VARCHAR(30),
  PRIMARY KEY (sno)
);
-- 教师表
CREATE TABLE t (
  tno CHAR(4) NOT NULL,
  tn VARCHAR(20) NOT NULL,
  sex CHAR(2),
  age INT,
  prof VARCHAR(20),
  maj VARCHAR(30),
  dept VARCHAR(30),
  sal DECIMAL(8,2),
  PRIMARY KEY (tno)
);
-- 选课表
CREATE TABLE sc (
  sno CHAR(4) NOT NULL,
  cno CHAR(4) NOT NULL,
  score DECIMAL(5,2),
  PRIMARY KEY (sno, cno),
  FOREIGN KEY (sno) REFERENCES s (sno),
  FOREIGN KEY (cno) REFERENCES c (cno)
);
-- 授课表
CREATE TABLE tc (
  tno CHAR(4) NOT NULL,
  cno CHAR(4) NOT NULL,
  tcdate DATE,
  PRIMARY KEY (tno, cno),
  FOREIGN KEY (tno) REFERENCES t (tno),
  FOREIGN KEY (cno) REFERENCES c (cno)
);

INSERT INTO c VALUES
('c1','Java程序设计',40), ('c2','程序设计基础',48), ('c3','线性代数',48),
('c4','数据结构',64), ('c5','数据库系统',56), ('c6','数据挖掘',32),
('c7','高等数学',60), ('c8','控制理论',32);

INSERT INTO s VALUES
('s1','王彤','女',18,'计算机','信息学院'),
('s2','苏乐','男',20,'信息','信息学院'),
('s3','林欣怡','女',19,'信息','信息学院'),
('s4','陶然','男',19,'自动化','工学院'),
('s5','魏立','男',17,'数学','理学院'),
('s6','何欣荣','女',21,'计算机','信息学院'),
('s7','赵琳琳','女',19,'数学','理学院'),
('s8','李轩','男',18,'自动化','工学院');

INSERT INTO t VALUES
('t1','刘杨','男',38,'教授','计算机','信息学院',3800.00),
('t2','石丽','女',28,'讲师','计算机','信息学院',2800.00),
('t3','顾伟','男',35,'副教授','计算机','信息学院',3200.00),
('t4','赵礼','男',45,'教授','自动化','工学院',4267.90),
('t5','赵希希','女',33,'副教授','数学','理学院',3332.67),
('t6','张刚','男',30,'讲师','计算机','工学院',2600.00);

INSERT INTO sc VALUES
('s1','c1',90.50), ('s1','c2',88.00),
('s2','c4',70.00), ('s2','c5',57.00), ('s2','c6',81.50), ('s2','c7',NULL),
('s3','c1',75.00), ('s3','c2',76.50), ('s3','c4',85.00),
('s4','c1',93.00), ('s4','c2',82.00), ('s4','c6',NULL), ('s4','c7',68.00),
('s5','c2',79.00), ('s5','c7',84.00),
('s7','c3',77.00), ('s7','c5',62.00), ('s7','c7',100.00),
('s8','c2',66.00), ('s8','c3',96.00);

INSERT INTO tc VALUES
('t1','c1','2021-09-03'), ('t1','c2','2021-09-04'),
('t2','c5','2021-03-06'), ('t2','c6','2021-09-06'),
('t3','c2','2021-03-08'), ('t3','c4','2021-09-08'),
('t4','c3','2021-03-10'),
('t5','c7','2021-09-12'), ('t5','c8','2021-03-15');

-- 打开事件调度器,建立实验三的表和两个事件
SET GLOBAL event_scheduler = ON;
CREATE TABLE tb_one (tno INT PRIMARY KEY AUTO_INCREMENT, ttime TIMESTAMP);
CREATE EVENT event_name4
ON SCHEDULE EVERY 5 SECOND
DO INSERT INTO tb_one VALUES (0, NOW());
CREATE EVENT event_name5
ON SCHEDULE EVERY 1 HOUR
STARTS CURRENT_DATE + INTERVAL 1 DAY
ENDS CURRENT_DATE + INTERVAL 1 WEEK
DO DELETE FROM tb_one;
SHOW EVENTS;
4-1

查看全部事件

讲义 · 查看事件
目的
用 SHOW EVENTS 和系统表 information_schema.EVENTS 查看当前库中的事件。
前提
已执行数据准备。
  1. 执行 SHOW EVENTS
  2. 从 information_schema.EVENTS 查询名称、类型、周期和状态

参考答案

可以直接复制到 Workbench 执行
SHOW EVENTS;
SELECT EVENT_NAME, EVENT_TYPE, INTERVAL_VALUE, INTERVAL_FIELD, STATUS
FROM information_schema.EVENTS
WHERE EVENT_SCHEMA = 'teaching';

语句解释

SHOW EVENTS显示当前库中的事件
EVENT_TYPEONE TIME 只执行一次,RECURRING 周期执行
INTERVAL_VALUE 与 INTERVAL_FIELD周期的数值和单位,例如 5 和 SECOND
执行后看:两个事件:event_name4 每 5 秒,event_name5 每 1 小时,状态都是 ENABLED。
4-2

查看一个事件

讲义 · 查看事件
目的
查看 event_name5 的完整定义。
前提
已完成实验 4-1。
  1. 执行 SHOW CREATE EVENT event_name5

参考答案

可以直接复制到 Workbench 执行
SHOW CREATE EVENT event_name5;

语句解释

Create Event这一列是建立事件的完整语句
STARTS 与 ENDSMySQL 把 CURRENT_DATE + INTERVAL 这样的表达式换算成了具体的时刻
ON COMPLETION NOT PRESERVE没有写时的默认值,事件结束后删除
执行后看:Create Event 一列中能看到 EVERY 1 HOUR、具体的 STARTS 和 ENDS 时刻、DO DELETE FROM tb_one。
4-3

修改事件

讲义 · 修改与删除事件
目的
修改 event_name4:改为每分钟执行一次,名称改为 name4,并加上注释。
前提
已完成实验 4-2。
  1. 用一条 ALTER EVENT 同时改周期、名称和注释
  2. 查看事件

参考答案

可以直接复制到 Workbench 执行
ALTER EVENT event_name4
ON SCHEDULE EVERY 1 MINUTE
RENAME TO name4
COMMENT '添加测试用例的注释';
SHOW EVENTS;

语句解释

ON SCHEDULE重新指定执行的时间
RENAME TO修改事件的名称
COMMENT修改注释,在 information_schema.EVENTS 的 EVENT_COMMENT 中能看到
执行后看:event_name4 变成了 name4,Interval value 为 1,Interval field 为 MINUTE。
4-4

暂停与恢复

讲义 · 修改与删除事件
目的
暂停 name4,查看它的状态,再恢复。然后让 event_name5 结束后保留下来。
前提
已完成实验 4-3。
  1. ALTER EVENT … DISABLE,查看状态
  2. ALTER EVENT … ENABLE,查看状态
  3. 把 event_name5 改为 ON COMPLETION PRESERVE

参考答案

可以直接复制到 Workbench 执行
ALTER EVENT name4 DISABLE;
SELECT EVENT_NAME, STATUS FROM information_schema.EVENTS
WHERE EVENT_SCHEMA = 'teaching';
ALTER EVENT name4 ENABLE;
ALTER EVENT event_name5 ON COMPLETION PRESERVE;
SELECT EVENT_NAME, STATUS, ON_COMPLETION FROM information_schema.EVENTS
WHERE EVENT_SCHEMA = 'teaching';

语句解释

DISABLE暂停事件,事件还在,但不再执行
ENABLE恢复执行
ON COMPLETION PRESERVE事件到期后保留,状态变为 DISABLED,不被删除
执行后看:第一个查询中 name4 为 DISABLED。第二个查询中两个事件都是 ENABLED,event_name5 的 ON_COMPLETION 为 PRESERVE。
4-5

例题 6

讲义 · 例题 6:定期调用存储过程
目的
运行例题 6:每周调用一次存储过程 pro_score,把每个学生的平均分和总分插入 week_score 表。
前提
已完成实验 4-4。
  1. 建立 week_score 表
  2. 用 DELIMITER 建立 pro_score 和 event_name6
  3. 稍等后查询 week_score,最后删除全部事件

参考答案

第 1 步
CREATE TABLE week_score (
  sno CHAR(5) NOT NULL,
  avgscore INT,
  sumscore INT,
  updatetime TIMESTAMP
);
DELIMITER $$
CREATE PROCEDURE pro_score()
BEGIN
  INSERT INTO week_score
  SELECT sno, AVG(score), SUM(score), NOW()
  FROM sc GROUP BY sno;
END $$
CREATE EVENT event_name6
ON SCHEDULE EVERY 1 WEEK
DO
BEGIN
  CALL pro_score();
END $$
DELIMITER ;
第 2 步 过两三秒
-- 过 3 秒以后再执行下面的语句
SELECT * FROM week_score;
DROP EVENT IF EXISTS event_name6;
DROP EVENT IF EXISTS event_name5;
DROP EVENT IF EXISTS name4;
SHOW EVENTS;

语句解释

DELIMITER过程体和事件体都有 BEGIN … END,要先改定界符
EVERY 1 WEEK建立后立刻执行第一次,以后每周一次
avgscore INT平均分存入整型字段时四舍五入,例如 89.25 存为 89
最后删除全部事件,免得周期事件一直执行
执行后看:week_score 有 7 行,没有选课的 s6 不在其中。最后 SHOW EVENTS 为空。
保山学院·人工智能教研室·曹鼎鼎