区别特性
特性 |
存储过程 |
触发器 |
定义 |
一组预编译的SQL语句,可通过调用来执行 |
一种自动执行的数据库对象,当某表的INSERT 、UPDATE 或DELETE 操作发生时触发 |
触发时机 |
需要显式调用(CALL ) |
由表的指定事件自动触发 |
使用场景 |
复杂的业务逻辑、多次复用的操作 |
实现数据自动校验、记录日志、同步数据等简单的自动化处理 |
参数支持 |
支持IN (输入)、OUT (输出)和INOUT (输入输出)参数 |
不支持参数 |
调用方式 |
通过CALL 存储过程名(参数) 调用 |
绑定到表的事件上,自动触发 |
依赖对象 |
独立于表,可以在多个表中使用 |
必须绑定到具体的表 |
维护难度 |
可维护性较好,适用于复杂逻辑 |
逻辑直接嵌入触发器,适合简单场景,但复杂触发器难以维护 |
性能影响 |
可以复用和优化,效率高 |
频繁触发时可能影响性能 |
案例演示
1.sql数据准备,以黑马数据演示
create database itcase;
show databases;
use itcast;
CREATE TABLE tb_users(
id INT PRIMARY KEY,
name VARCHAR(255),
phone VARCHAR(20),
email VARCHAR(255),
profession VARCHAR(255),
age INT,
gender INT,
status INT,
createtime DATETIME
);
INSERT INTO tb_users (id, name, phone, email, profession, age, gender, status, createtime)
VALUES (1, '吕布', '17799990000', 'lvbu666@163.com', '软件工程', 23, 1, 6, '2001-02-02 00:00:00'),
(2, '曹操', '17799990001', 'caocao666@qq.com', '通讯工程', 33, 1, 0, '2001-03-05 00:00:00'),
(3, '赵云', '17799990002', '177999900@139.com', '英语', 34, 1, 2, '2002-03-02 00:00:00'),
(4, '孙悟空', '17799990003', '177999900@sina.com', '工程造价', 54, 1, 0, '2001-07-02 00:00:00'),
(5, '花木兰', '17799990004', '19980729@sina.com', '软件工程', 23, 2, 1, '2001-04-22 00:00:00'),
(6, '大乔', '17799990005', 'daqiao666@sina.com', '舞蹈', 22, 2, 0, '2001-02-07 00:00:00'),
(7, '露娜', '17799990006', 'luna_love@sina.com', '应用数学', 24, 2, 0, '2001-02-08 00:00:00'),
(8, '程咬金', '17799990007', 'chengyaojin@163.com', '化工', 38, 1, 0, '2001-05-23 00:00:00'),
(9, '项羽', '17799990008', 'xiaoyu666@qq.com', '金属材料', 43, 1, 1, '2001-09-18 00:00:00'),
(10, '白起', '17799990009', 'baiqi666@163.com', '机械工程及其自动化', 27, 1, 2, '2001-08-16 00:00:00'),
(11, '韩信', '17799990010', 'hanxin520@163.com', '无机非金属材料工程', 27, 1, 0, '2001-06-12 00:00:00'),
(12, '荆轲', '17799990011', 'jingke123@163.com', '会计', 29, 1, 0, '2001-05-11 00:00:00'),
(13, '兰陵王', '17799990012', 'lanlinwang666@126.com', '工程造价', 44, 1, 1, '2001-04-09 00:00:00'),
(14, '狂铁', '17799990013', 'kuangtie@sina.com', '应用数学', 43, 1, 2, '2001-04-10 00:00:00'),
(15, '貂蝉', '17799990014', '8495848374@qq.com', '软件工程', 40, 2, 1, '2001-02-12 00:00:00'),
(16, '妲己', '17799990015', '2782382939@qq.com', '软件工程', 31, 2, 0, '2001-01-30 00:00:00'),
(17, '半月', '17799990016', 'xiaomin2001@sina.com', '工业经济', 35, 2, 0, '2000-05-03 00:00:00'),
(18, '赢政', '17799990017', '8839434342@qq.com', '化工', 38, 1, 1, '2001-08-08 00:00:00'),
(19, '狄仁杰', '17799990018', 'jujiamlm816@163.com', '国际贸易', 30, 1, 1, '2007-03-12 00:00:00'),
(20, '安琪拉', '17799990019', 'jdodmlh@126.com', '城市规划', 51, 2, 0, '2001-08-15 00:00:00'),
(21, '典韦', '17799990020', 'ycauanjian@163.com', '城市规划', 52, 1, 0, '2000-04-12 00:00:00'),
(22, '廉颇', '17799990021', 'lianpo321@126.com', '土木工程', 19, 1, 3, '2002-07-18 00:00:00'),
(23, '后羿', '17799990022', 'altycj2000@139.com', '城市园林', 20, 1, 0, '2002-03-10 00:00:00'),
(24, '姜子牙', '17799990023', '3748384@qq.com', '工程造价', 29, 1, 4, '2003-05-26 00:00:00');
2.存储过程、触发器、游标案例
create procedure p1()
begin
select count(*) from student;
end;
call p1();
select * from information_schema.ROUTINES where ROUTINE_SCHEMA = 'itcast';
show create procedure p1;
drop procedure if exists p1;
show variables;
show session variables;
show session variables like 'auto%';
show global variables like 'auto%';
select @@autocommit;
set session autocommit = 0;
select @@autocommit;
select @@session.autocommit;
set session autocommit = 1;
set @myname = 'itcast';
set @myage := 10;
set @mygender := '男', @myhobby := 'java';
select @mycolor := 'red';
select count(*) into @mycount from tb_users;
select @myname, @myage, @mygender, @myhobby;
select @mycolor, @mycount;
create procedure p2()
begin
declare stu_count int default 0;
select count(*) into stu_count from student;
set stu_count = 55;
select stu_count;
end;
call p2();
create procedure p3()
begin
declare score int default 58;
declare rs varchar(10);
if score >= 85 then
set rs = '优秀';
elseif score >= 60 then
set rs = '及格';
else
set rs = '不及格';
end if;
select rs;
end;
call p3();
create procedure p4(in score int, out rs varchar(10))
begin
if score >= 85 then
set rs = '优秀';
elseif score >= 60 then
set rs = '及格';
else
set rs = '不及格';
end if;
end;
call p4(98, @rs);
select @rs;
create procedure p5(inout score double)
begin
set score := score * 0.5;
end;
set @rs = 178;
call p5(@rs);
select @rs;
call p4(89, @rs);
select @rs;
create procedure p6(in month int)
begin
declare rs varchar(10);
case
when month >= 3 and month <= 5 then
set rs := '第一季度';
when month >= 6 and month <= 8 then
set rs := '第二季度';
when month >= 9 and month <= 11 then
set rs := '第三季度';
when month >= 12 and month <= 2 then
set rs := '第四季度';
else
set rs := '非法参数';
end case;
select concat('您输入的月份为:', month, ',所属季度为:', rs);
end;
drop procedure if exists p6;
call p6(7);
create procedure p7(in n int)
begin
declare total int default 0;
while n>0 do
set total := total + n;
set n := n - 1;
end while;
select total;
end;
call p7(100);
create procedure p8(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 p8(10);
drop procedure if exists p8;
create procedure p9(in n int)
begin
declare total int default 0;
sum:loop
if n <= 0 then
leave sum;
end if;
set total := total + n;
set n := n - 1;
end loop sum;
select total;
end;
call p9(15);
create procedure p10(in n int)
begin
declare total int default 0;
sum:loop
set total := total + n;
set n := n - 1;
if n < 0 then
leave sum;
end if;
end loop sum;
select total;
end;
call p10(15);
create procedure p11(in n int)
begin
declare total int default 0;
evenSum:loop
if n % 2 = 1 then
set n := n - 1;
iterate evenSum;
end if;
set total := total + n;
set n := n - 1;
if n < 0 then
leave evenSum;
end if;
end loop evenSum;
select total;
end;
drop procedure if exists p11;
call p11(2);
create procedure p12(in uage int)
begin
declare uname varchar(100);
declare upro varchar(100);
declare u_cursor cursor for select name, profession from tb_users where age <= uage;
declare exit handler for sqlstate '02000' close u_cursor;
drop table if exists tb_user_pro;
create table tb_user_pro(
id int primary key auto_increment,
name varchar(100),
profession varchar(100)
);
open u_cursor;
while true do
fetch u_cursor into uname, upro;
insert into tb_user_pro values (id, uname, upro);
end while;
close u_cursor;
end;
drop procedure if exists p12;
call p12(40);
create function fun1(n int)
returns int deterministic
begin
declare total int default 0;
while n > 0 do
set total := total + n;
set n := n - 1;
end while;
return total;
end;
select fun1(100);
create table user_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;
create trigger tb_user_insert_trigger
after insert on tb_users for each row
begin
insert into user_logs(id, operation, operate_time, operate_id, operate_params) values
(null, 'insert', now(), new.id, concat('插入内容为:id=', new.id, ', name=', new.name, ', phone=', new.phone, ', profession=', new.profession));
end;
show triggers;
drop trigger if exists tb_user_insert_trigger;
insert into tb_users(id, name, phone, email, profession, age, gender, status, createtime) VALUES (26,'二皇子','18809091211','erhuangzi@163.com','软件工程',23,'1','1',now());
create trigger tb_user_update_trigger
after update on tb_users for each row
begin
insert into user_logs(id, operation, operate_time, operate_id, operate_params) values
(null, 'update', now(), new.id,
concat('更新之前的数据:id=', old.id, ',name=', old.name, ',phone=', old.phone, ',profession=', old.profession,
' | 更新之后的数据:id=', new.id, ',name=', new.name, ',phone=', new.phone, ',profession=', new.profession));
end;
show triggers;
update tb_users set age = 32 where id = 23;
update tb_users set profession = '会计' where id <= 5;
drop trigger if exists tb_user_update_trigger;
create trigger tb_user_delete_trigger
after delete on tb_users for each row
begin
insert into user_logs(id, operation, operate_time, operate_id, operate_params) VALUES
(null, 'delete', now(), old.id,
concat('删除之前的数据:id=', old.id, ',name=', old.name, ',phone=', old.phone, 'email=', old.email, ',profession=', old.profession));
end;
show triggers;
drop trigger if exists tb_user_delete_trigger;
delete from tb_users where id = 25;