mysql存储过程及函数
- 基本语法
- IF语句
- while循环
- repeat循环
- loop循环
- 游标cursor
- 存储函数
- 触发器
基本语法
-- 创建存储过程
delimiter $
CREATE PROCEDURE pro_test01()
BEGIN
SELECT 'Hello Mysql';
END $
delimiter ;
-- 调用存储过程
CALL pro_test01();
-- 查看存储过程
-- 查询某数据库中的所有的存储过程
select name from mysql.proc where db='数据库名';
-- 查询存储过程的状态信息
show procedure status;
-- 查询某个存储过程的定义
show create procedure 数据库名.存储过程名 \G;
delimiter
该关键字用来声明SQL语句的分隔符 , 告诉 MySQL 解释器,该段命令是否已经结束了,mysql是否可以执行了。
默认情况下,delimiter是分号;。在命令行客户端中,如果有一行命令以分号结束,那么回车后,mysql将会执行该命令。
IF语句
DROP PROCEDURE IF EXISTS pro_test1;
CREATE PROCEDURE pro_test1(IN height INT)
BEGIN
DECLARE description VARCHAR(50);
IF height >= 180 THEN
SET description = '身材高挑';
ELSEIF height >= 170 THEN
SET description = '标准身材';
ELSE
SET description = '一般身材';
END IF;
SELECT description;
END
CALL pro_test1(180);
while循环
WHILE condition DO
statements
END WHILE;
DROP PROCEDURE pro_calculate_input;
-- 从0加到n的值 -- 累加和
CREATE PROCEDURE pro_calculate_input(IN n INT)
BEGIN
DECLARE total INT DEFAULT 0;
DECLARE start_num INT DEFAULT 0;
WHILE start_num <= n DO
SET total = total + start_num;
SET start_num = start_num + 1;
END WHILE;
SELECT total;
END
CALL pro_calculate_input(2);
repeat循环
REPEAT
statements
UNTIL continue_condition
END REPEAT;
DROP PROCEDURE pro_calculate_input;
CREATE PROCEDURE pro_calculate_input(IN n INT)
BEGIN
DECLARE total INT DEFAULT 0;
REPEAT
SET total = total + n;
SET n = n - 1;
UNTIL n = 0
END REPEAT;
SELECT total;
END
CALL pro_calculate_input(2);
loop循环
[custom_label:] LOOP
statemens
-- 通常使用 leave 语句退出循环
END LOOP [custom_label]
DROP PROCEDURE pro_calculate_input;
CREATE PROCEDURE pro_calculate_input(IN n INT)
BEGIN
DECLARE total INT DEFAULT 0;
calc:LOOP
SET total = total + n;
SET n = n - 1;
IF n <= 0 THEN
leave calc;
END IF;
END LOOP calc;
SELECT total;
END
CALL pro_calculate_input(2);
游标cursor
-- 声明游标
DECLARE cursor_name CURSOR FOR select_statement;
-- 打开游标
OPEN cursor_name;
-- 遍历游标
FETCH cursor_name INTO var_name1 [, var_name2];
-- 关闭游标
CLOSE cursor_name;
DROP PROCEDURE IF EXISTS pro_cursor_print;
CREATE PROCEDURE pro_cursor_print()
BEGIN
DECLARE v_id INT(11);
DECLARE v_username VARCHAR(10);
DECLARE v_money DECIMAL(10,2);
DECLARE has_data_flag INT DEFAULT 1;
-- 声明游标
DECLARE account_result cursor FOR SELECT id,username,money FROM account;
DECLARE EXIT handler FOR NOT FOUND SET has_data_flag = 0;
-- 打开游标
OPEN account_result;
-- 遍历游标
REPEAT
FETCH account_result INTO v_id,v_username,v_money;
SELECT CONCAT('v_id=',v_id,', v_username=',v_username,', v_money',v_money);
-- 退出循环
UNTIL has_data_flag = 0
END REPEAT;
-- 关闭游标
CLOSE account_result;
END
CALL pro_cursor_print();
存储函数
DROP TABLE IF EXISTS `payment`;
CREATE TABLE `payment` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`serial` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- 语法
CREATE FUNCTION function_name([param type ... ])
RETURNS type
BEGIN
...
END;
定义一个存储函数, 查询表中总记录数 ;
-- 例子
drop function if exists count_record;
create function count_record()
returns int
begin
declare v_rslt int ;
select count(*) into v_rslt from payment;
return v_rslt;
end
触发器
触发器是与表有关的数据库对象,指在 insert/update/delete 之前或之后,触发并执行触发器中定义的SQL语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性 , 日志记录 , 数据校验等操作 。
使用别名 OLD 和 NEW 来引用触发器中发生变化的记录内容,这与其他的数据库是相似的。
行级触发器
语句级触发器
开启创建trigger权限
-- 使用root用户登录执行如下操作
set global log_bin_trust_function_creators=1
show variables like 'log_bin_trust_function_creators'
触发器类型 | NEW 和 OLD的使用 |
INSERT 型触发器 | NEW 表示将要或者已经新增的数据 |
UPDATE 型触发器 | OLD 表示修改之前的数据 , NEW 表示将要或已经修改后的数据 |
DELETE 型触发器 | OLD 表示将要或者已经删除的数据 |
create trigger trigger_name
before/after insert/update/delete
on tbl_name
[ for each row ] -- 行级触发器
begin
trigger_stmt ;
end;
创建logs表
create table payment_logs(
id int(11) not null auto_increment,
operation varchar(20) not null comment '操作类型, insert/update/delete',
operate_time datetime not null comment '操作时间',
operate_id int(11) not null comment '操作表的ID',
operate_params varchar(500) comment '操作参数',
primary key(`id`)
)engine=innodb default charset=utf8;
drop trigger if exists payment_logs_insert_trigger;
create trigger emp_logs_insert_trigger
after insert
on emp
for each row
begin
insert into emp_logs (id,operation,operate_time,operate_id,operate_params) values(null,'insert',now(),new.id,concat('插入后(id:',new.id,', name:',new.name,', age:',new.age,', salary:',new.salary,')'));
end $
DROP TABLE IF EXISTS `michael_student`;
CREATE TABLE `michael_student` (
`id` bigint NOT NULL,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`sync_time` datetime NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
DROP TRIGGER IF EXISTS `michael_student_trigger`;
delimiter ;;
CREATE TRIGGER `michael_student_trigger` AFTER DELETE ON `michael_student` FOR EACH ROW begin
insert into nqi_wfw.michael_student(id,name,sync_time)
values(old.id,old.name,old.sync_time);
end
;;
delimiter ;
系统变量:全局变量、会话变量
状态变量:
show global variables \G;
show global variables like ‘%version%’ \G;
show global variables where variable_name like ‘character%’;
show global variables where variable_name like ‘%log%’ and value=‘off’;
show session variables \G;
show variables;
SELECT @@global.wait_timeout;
SELECT @@session.wait_timeout;
SELECT @@global.pid_file;
SELECT @@session.warning_count;
在写存储过程时,如果需要调用系统变量的值,可以通过如下方法调用。
@@GLOBAL.var_name
@@SESSION.var_name
@@var_name 表示优先从会话级别获取变量值。
查看状态变量。
show status;
设置系统变量的语法:
SET GLOBAL var_name = value;
SET @@GLOBAL.var_name = value;
SET SESSION var_name = value;
SET @@SESSION.var_name = value;
不指定级别默认设置会话级别的变量。
SET var_name = value;
状态变量对于用户来说是只读的。