#存储过程
#存储函数
#事件event
show VARIABLES like '%schedule%';
#能查看所有存储过程
SHOW PROCEDURE STATUS;
#c查看某个存储过程具体信息
SHOW CREATE PROCEDURE DeleteOldData;
show EVENTS;
select DATE_SUB(NOW(), INTERVAL 3 MONTH) from dual;
DELIMITER $$
CREATE PROCEDURE DeleteOldData()
BEGIN
-- 计算三个月前的日期
DECLARE three_months_ago DATE;
SET three_months_ago = DATE_SUB(NOW(), INTERVAL 3 MONTH);
-- 删除三个月前的数据
DELETE FROM books7
WHERE uptime < three_months_ago;
-- 提交事务
COMMIT;
END$$
DELIMITER ;
CREATE EVENT IF NOT EXISTS weekly_delete_old_data
ON SCHEDULE EVERY 1 WEEK
STARTS '2024-08-25 02:00:00' -- 设定为你想要的起始时间
DO
CALL DeleteOldData();
CREATE EVENT minly_delete_old_data
ON SCHEDULE EVERY 1 MINUTE
STARTS CURRENT_TIMESTAMP -- 设定为你想要的起始时间
DO
CALL DeleteOldData();
SHOW CREATE PROCEDURE DeleteOldData;
show EVENTS;
select * from books7;
ALTER EVENT minly_delete_old_data ON COMPLETION PRESERVE ENABLE;
ALTER EVENT minly_delete_old_data ON COMPLETION PRESERVE DISABLE;
show VARIABLES like '%schedule%';
CREATE PROCEDURE GetOfficeByCountry(IN N int)
BEGIN
SELECT *
FROM scores
WHERE id < N;
END
call GetOfficeByCountry(5);
-- show create procedure GetOfficeByCountry;
--
--
-- characteristics 表示创建存储过程时指定的对存储过程的约束条件,其取值信息如下:
-- LANGUAGE SQL :说明存储过程执行体是由SQL语句组成的,当前系统支持的语言为SQL。
-- [NOT] DETERMINISTIC :指明存储过程执行的结果是否确定。DETERMINISTIC表示结果是确定
-- 的。每次执行存储过程时,相同的输入会得到相同的输出。NOT DETERMINISTIC表示结果是不确定
-- 的,相同的输入可能得到不同的输出。如果没有指定任意一个值,默认为NOT DETERMINISTIC。
-- { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } :指明子程序使
-- 用SQL语句的限制。
-- CONTAINS SQL表示当前存储过程的子程序包含SQL语句,但是并不包含读写数据的SQL语句;
-- NO SQL表示当前存储过程的子程序中不包含任何SQL语句;
-- READS SQL DATA表示当前存储过程的子程序中包含读数据的SQL语句;
-- MODIFIES SQL DATA表示当前存储过程的子程序中包含写数据的SQL语句。
-- 默认情况下,系统会指定为CONTAINS SQL。
-- SQL SECURITY { DEFINER | INVOKER } :执行当前存储过程的权限,即指明哪些用户能够执
-- 行当前存储过程。
-- DEFINER 表示只有当前存储过程的创建者或者定义者才能执行当前存储过程;
-- INVOKER 表示拥有当前存储过程的访问权限的用户能够执行当前存储过程。
-- 如果没有设置相关的值,则MySQL默认指定值为DEFINER。
-- CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型,...)
-- [characteristics ...]
-- BEGIN
-- 存储过程体
-- END
-- 修饰符 返回类型 方法名(参数类型 参数名,...){
-- 方法体;
-- }
-- LANGUAGE SQL
-- | [NOT] DETERMINISTIC
-- | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
-- | SQL SECURITY { DEFINER | INVOKER }
-- | COMMENT 'string'
-- COMMENT 'string' :注释信息,可以用来描述存储过程。
#存储过程语法:
DELIMITER $
CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型,...)
[characteristics ...]
BEGIN
sql语句1;
sql语句2;
END $
DELIMITER ;
#创建
delimiter $
create PROCEDURE selectEmp()
COMMENT '查看所有员工信息'
begin
select * from employees ;
end $
delimiter ;
#调用
call selectEmp();
#删除存储过程
DROP PROCEDURE [ IF EXISTS ] <过程名>
DROP PROCEDURE some_salary;
show create PROCEDURE selectEmp;
# OUT参数 定义
DELIMITER //
CREATE PROCEDURE show_max_salary(OUT ms DOUBLE)
BEGIN
SELECT MAX(salary) INTO ms FROM employees;
END //
DELIMITER ;
#调用
call show_max_salary(@maxsa);
select @maxsa;
# IN参数 定义
DELIMITER //
CREATE PROCEDURE show_someone_did(IN d_id VARCHAR(20))
COMMENT '查看所有部门员工信息'
BEGIN
SELECT * FROM employees WHERE department_id = d_id;
END //
DELIMITER ;
#调用
call show_someone_did(30);
# IN 、OUT参数
DELIMITER $$
create procedure some_salary(IN seid int,OUT sal DOUBLE)
COMMENT '某人薪资'
BEGIN
select salary into sal FROM employees where employee_id = seid;
END $$
DELIMITER ;
#调用
call some_salary(108,@sal);
select @sal;
## INOUT参数
DELIMITER $$
CREATE PROCEDURE show_mgr_name(INOUT empname VARCHAR(20))
BEGIN
SELECT last_name INTO empname FROM employees
WHERE employee_id = (SELECT manager_id FROM employees WHERE last_name=empname);
END $$
DELIMITER ;
set @empname = 'Chen';
call show_mgr_name(@empname);
select @empname;
#存储函数
#参数列表:指定参数为IN、OUT或INOUT只对PROCEDURE是合法的,FUNCTION中总是默认为IN参数
#characteristic 创建函数时指定的对函数的约束。取值与创建存储过程时相同
CREATE FUNCTION 函数名(参数名 参数类型,...)
RETURNS 返回值类型
[characteristics ...]
BEGIN
函数体 #函数体中肯定有 RETURN 语句
END
DELIMITER $
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
READS SQL DATA
BEGIN
set N = N - 1;
RETURN (
select ifnull((
select distinct salary
from employees
order by salary desc limit N,1),null) as getNthHighestSalary
);
END $
DELIMITER ;
#调用
select getNthHighestSalary(2);
#删除
drop FUNCTION getNthHighestSalary;
DELIMITER $$
CREATE FUNCTION count_by_id(dept_id INT) RETURNS INT
LANGUAGE SQL
NOT DETERMINISTIC
READS SQL DATA
SQL SECURITY DEFINER
COMMENT '查询部门平均工资'
BEGIN
RETURN (SELECT COUNT(*) FROM employees WHERE department_id = dept_id);
END $$
DELIMITER ;
#调用
-- SET @dept_id = 50;
-- SELECT count_by_id(@dept_id);
select count_by_id(30);
-- 若在创建存储函数中报错“ you might want to use the less safe
-- log_bin_trust_function_creators variable ”
-- 加上必要的函数特性或者如下设置
#SET GLOBAL log_bin_trust_function_creators = 1;
#事件event
#查看事件开启状态
show VARIABLES like '%event_scheduler%';
#在my.cnf中配置event_scheduler=1或者event_scheduler=0开可控制是否开启。不配置则默认为关闭
#启动事件调度器
SET GLOBAL event_scheduler = 1;
SET GLOBAL event_scheduler = on;
#关闭事件调度器
SET GLOBAL event_scheduler = 0;
SET GLOBAL event_scheduler = off;
#查看具体定义的事件
show EVENTS;
#禁用某个事件
ALTER EVENT minly_delete_old_data DISABLE;
#启用某个事件
ALTER EVENT minly_delete_old_data ENABLE;
#删除某个事件
DROP EVENT my_event;
-- 开启指定事件:ALTER EVENT 具体事件名称 ON COMPLETION PRESERVE ENABLE;
-- 关闭指定事件:ALTER EVENT 具体的事件名称 ON COMPLETION PRESERVE DISABLE;
-- 查看事件:SHOW EVENTS; 或者 SELECT * FROM INFORMATION_SCHEMA.'EVENTS';
-- 删除指定事件:DROP EVENT IF EXISTS 具体事件名称;
#查看当前存在的事件状态信息
show EVENTS;
#通过查询information_schema数据库中的EVENTS表来查看事件的执行情况
SELECT * FROM information_schema.EVENTS;
#查看调度器线程
show processlist;
#创建语法
CREATE
[DEFINER = { user | CURRENT_USER }]
EVENT
[IF NOT EXISTS]
event_name
ON SCHEDULE schedule
[ON COMPLETION [NOT] PRESERVE]
[ENABLE | DISABLE | DISABLE ON SLAVE]
[COMMENT 'comment']
DO event_body;
schedule:
AT timestamp [+ INTERVAL interval] ...
| EVERY interval
[STARTS timestamp [+ INTERVAL interval] ...]
[ENDS timestamp [+ INTERVAL interval] ...]
interval:
quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |
WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |
DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}
-- event_name :创建的event名字(唯一确定的)。
-- ON SCHEDULE:计划任务。
-- schedule: 决定event的执行时间和频率(注意时间一定要是将来的时间,过去的时间会出错),有两种形式 AT和EVERY。
-- [ON COMPLETION [NOT] PRESERVE]: 可选项,默认是ON COMPLETION NOT PRESERVE 即计划任务执行完毕后自动drop该事件;ON COMPLETION PRESERVE则不会drop掉。
-- [COMMENT 'comment'] :可选项,comment 用来描述event;相当注释,最大长度64个字节。
-- [ENABLE | DISABLE] :设定event的状态,默认ENABLE:表示系统尝试执行这个事件, DISABLE:关闭该事情,可以用alter修改
-- DO event_body: 需要执行的sql语句(可以是复合语句)。CREATE EVENT在存储过程中使用时合法的。
select DATE_SUB(NOW(), INTERVAL 3 MONTH) from dual;
select DATE_ADD(NOW(), INTERVAL 5 MONTH)from dual;
DELIMITER $$
CREATE PROCEDURE DeleteOldData()
BEGIN
-- 计算三个月前的日期
DECLARE three_months_ago DATE;
SET three_months_ago = DATE_SUB(NOW(), INTERVAL 3 MONTH);
-- 删除三个月前的数据
DELETE FROM books7
WHERE uptime < three_months_ago;
-- 提交事务
COMMIT;
END$$
DELIMITER ;
CREATE EVENT IF NOT EXISTS weekly_delete_old_data
ON SCHEDULE EVERY 1 WEEK
STARTS '2024-08-25 02:00:00' -- 设定为你想要的起始时间
DO
CALL DeleteOldData();
#every
CREATE EVENT minly_delete_old_data
ON SCHEDULE EVERY 1 MINUTE
STARTS CURRENT_TIMESTAMP -- 设定为你想要的起始时间
DO
CALL DeleteOldData();
#at
CREATE EVENT IF NOT EXISTS at_d_test
ON SCHEDULE at '2024-09-11 17:18:00'
DO
CALL DeleteOldData();
SHOW CREATE PROCEDURE DeleteOldData;
show EVENTS;
常用的时间间隔示例:
#(1)每隔10秒钟执行
ON SCHEDULE EVERY 10 SECOND
#(2)每隔10分钟执行
ON SCHEDULE EVERY 10 MINUTE
#(3)每天凌晨5点执行
ON SCHEDULE EVERY 1 DAY
STARTS DATE_ADD(DATE_ADD(CURDATE(),INTERVAL 1 DAY), INTERVAL 5 HOUR)
#(4)每隔3个月执行,从现在起2周后开始
ON SCHEDULE EVERY 3 MONTH STARTS CURRENT_TIMESTAMP + 2 WEEK
#(5)每隔3小时执行,从现在起10分钟后开始,1个星期后结束
ON SCHEDULE EVERY 3 HOUR
STARTS CURRENT_TIMESTAMP + INTERVAL 10 MINUTE
ENDS CURRENT_TIMESTAMP + INTERVAL 1 WEEK
#(6)在2022-06-30晚上9点执行
ON SCHEDULE AT '2022-06-30 21:00:00'
#查看所有全局变量
SHOW GLOBAL VARIABLES;
#查看所有会话变量
SHOW SESSION VARIABLES;
或
SHOW VARIABLES;
#查看满足条件的部分系统变量。
SHOW GLOBAL VARIABLES LIKE '%events%';
#查看满足条件的部分会话变量
SHOW SESSION VARIABLES LIKE '%events%';
#触发器
CREATE TABLE bookst (
id INT PRIMARY KEY AUTO_INCREMENT,
titles VARCHAR(100),
author_id INT,
uptime TIMESTAMP DEFAULT NOW()
);
CREATE TABLE bookstb (
id INT PRIMARY KEY AUTO_INCREMENT,
old_id VARCHAR(100),
titles VARCHAR(100),
author_id VARCHAR(50),
uptime TIMESTAMP DEFAULT NOW(),
users VARCHAR(100)
);
CREATE TABLE bookstt (
id INT PRIMARY KEY AUTO_INCREMENT,
titles VARCHAR(100),
author_id INT,
uptime TIMESTAMP DEFAULT NOW()
);
CREATE TABLE bookst (
id INT PRIMARY KEY AUTO_INCREMENT,
titles VARCHAR(100),
author_id INT,
uptime TIMESTAMP DEFAULT NOW()
);
delimiter $$
create trigger salary_check
before insert on emp for each row
BEGIN
DECLARE mgrsalary double;
select salary INTO mgrsalary from emp where eid=new.mid;
if new.salary > mgrsalary then
SIGNAL SQLSTATE 'HY000' SET MESSAGE_TEXT = '薪资高于领导薪资错误';
END IF;
END $$
delimiter ;
insert into emp values(DEFAULT,'etts1',3000,2);
insert into emp values(DEFAULT,'etts2',5000,2);
#查看当前数据库的所有触发器的定义
show triggers;
#查看当前数据库中某个触发器的定义
show create trigger salary_check;
#从系统库information_schema的TRIGGERS表中查询触发器的信息
SELECT * FROM information_schema.TRIGGERS;
#删除触发器
DROP TRIGGER IF EXISTS delbokbak;
-- 注意,如果在子表中定义了外键约束,并且外键指定了ON UPDATE/DELETE CASCADE/SET NULL子句,此
-- 时修改父表被引用的键值或删除父表被引用的记录行时,也会引起子表的修改和删除操作,此时基于子
-- 表的UPDATE和DELETE语句定义的触发器并不会被激活。
-- 例如:基于子表员工表(t_employee)的DELETE语句定义了触发器t1,而子表的部门编号(did)字段定
-- 义了外键约束引用了父表部门表(t_department)的主键列部门编号(did),并且该外键加了“ON
-- DELETE SET NULL”子句,那么如果此时删除父表部门表(t_department)在子表员工表(t_employee)
-- 有匹配记录的部门记录时,会引起子表员工表(t_employee)匹配记录的部门编号(did)修改为NULL,
-- mysql> update demo.membermaster set memberdeposit=20 where memberid = 2;
-- ERROR 1054 (42S22): Unknown column 'aa' in 'field list'
-- 但是此时不会激活触发器t1。只有直接对子表员工表(t_employee)执行DELETE语句时才会激活触发器
-- t1。
--
create trigger insetb_af
after insert on bookst for each row
BEGIN
insert into bookstt VALUES (DEFAULT,new.titles,new.author_id,NOW());
end
insert into bookst() VALUES
(default,'book2',2,DEFAULT),
(default,'book2',2,DEFAULT),
(default,'book2',2,DEFAULT),
(default,'book2',2,DEFAULT),
(default,'book2',2,DEFAULT),
(default,'book2',2,DEFAULT),
(default,'book2',2,DEFAULT),
(default,'book2',2,DEFAULT);
create trigger uptb_bf
before update on bookst for each row
begin
update bookstt set titles=new.titles,author_id=new.author_id,uptime=NOW() WHERE id = old.id;
end
update bookst set titles='newtitles111',author_id=3,uptime=NOW() WHERE id = 2;
create trigger delbokbak
before delete on bookst for each row
begin
insert into bookstb VALUES(DEFAULT,old.id,CONCAT('旧标题:',old.titles),old.author_id,NOW(),USER());
end
delete from bookst where id = 8;
delete from bookst where id in (6,7) ;
#eg
select score,DENSE_RANK() over(ORDER BY score desc) as 'rank' from Scores;
select s1.score,count(DISTINCT s2.score) as 'rank' from Scores as s1,Scores as s2 WHERE s1.score <= s2.score GROUP BY s1.id ORDER BY s1.score desc;
CREATE TABLE `tb_dau` (
`fdate` date DEFAULT NULL,
`user_id` int DEFAULT NULL
);
select user_id '用户id', MAX(c_day) '最长连续登录天数' from
(SELECT user_id,MAX(date_sort)-MIN(date_sort)+1 as c_day from
(select
user_id,
fdate,
DENSE_RANK() over(partition by user_id order by fdate) as date_sort,
date_sub(fdate, interval row_number() over(partition by user_id order by fdate) day) as b_date
from tb_dau
where fdate between '2023-01-01' and '2023-12-31' AND user_id = 10000) as t1
GROUP BY b_date) as t2 GROUP BY user_id;