MySQL学习(十六)

MySQL高级部分
触发器
触发器是一类特殊的事务,可以监视某种数据操作(insert/update/delete),并触发相关的操作(insert/update/delete)
触发器创建语法之4要素
1 监视地点table
2 监视事件insert/update/delete
3 触发时间after/before
4 触发事件

查看已有的触发器

show triggers

删除已有的触发器

drop trigger triggerName

创建一个触发器

create trigger t1
after
insert on ord
for each row
begin
update goods1 set num = num - 2 where gid = 1;
end$

上面语句中,如果insert(被监视的语句),产生的数据,能否在触发器中引用到?

更改之后的触发器,引入了参数

create trigger t2
after
insert on ord
for each row
begin
update goods1 set num = num -new.much where gid = new.gid;
end$

删除订单的触发器

create trigger t3
after
delete 
on ord
for each row
begin
update goods1 set num = num + old.much where gid = old.gid;
end$

改订单数量

create trigger t4
before
update 
on ord
for each row
begin
update goods1 set num = num + (old.much - new.much) where gid = old.gid;
end$

思考:before目前似乎没有看出与after的区别?
再思考:如果剩余的库存量只有3个,但客户要买10个,就会出现问题
一个问题

能否在购买量 much > 库存量num时,把much自动改为num
提示:before的作用
在t2的基础上,完成much与num的判断

create trigger t5
after
insert on ord
for each row
begin
declare 
rnum int;
select num into rnum from goods1 where gid = new.gid;
if new.much > rnum then
    set new.much = rnum;
end if
update goods1 set num = num -new.much where gid = new.gid;
end$

提示错误

ERROR 1362 (HY000): Updating of NEW row is not allowed in after trigger

原因:insert之后,new行已经插入到表中,成为事实,改new已经晚了
修改
在t2的基础上,完成much与num的判断

create trigger t5
before
insert on ord
for each row
begin
declare 
rnum int;
select num into rnum from goods1 where gid = new.gid;
if new.much > rnum then
    set new.much = rnum;
end if;
update goods1 set num = num -new.much where gid = new.gid;
end$

insert 只能引用新行 new
delete 只能引用旧行 old
update可以引用新行和旧行,新行为new,旧行为old

触发器for each row是干吗的?
在oracle的触发器中,触发器可以分为语句级触发器和行级触发器
执行
update xxtable set xxx=xxx where id > 100; #修改了100行
那么sqlN会被触发几次?
100次

create trigger t5
before
insert on ord
for each row #每一行受影响,触发器都执行,叫做行级触发器
begin
declare 
rnum int;
select num into rnum from goods1 where gid = new.gid;
if new.much > rnum then
    set new.much = rnum;
end if;
update goods1 set num = num -new.much where gid = new.gid;
end$
在orcal中
for each row如果不写,无论update语句一次影响了多少行,都只执行一次。
比如:1人下了订单,买了5件商品,insert 5 次,可以用行级触发器,修改5次库存,
用语句级触发,insert一条发货提醒。
遗憾的是,MySQL目前不支持语句级触发器。
for each row 声明行级触发器

存储过程和函数
创建存储过程的语法
create procedure procedureName()
begin
--sql语句
end$
调用存储过程
call procedure();
删除存储过程

drop procedure procedureName

创建存储过程语法

create procedure p1()
begin 
    select 'hello' from dual;
end$

存储过程是可以编程的,意味着可以使用变量,表达式,控制结构来完成复杂的功能
在存储过程中,用declare声明变量
格式 declare 变量名 变量类型 [default 默认值]
引入变量

create procedure p2()
begin
    declare age int default 18;
    declare height int default 180;
    select concat('年龄是',age,'身高是',height);
end$

存储过程中,变量可以做sql语句中合法的运算,如加减乘除,
注意,运算的结果,如何赋值给变量
set 变量名 := expression

create procedure p3()
begin
    declare age int default 18;
    declare height int default 180;
    set age := age + 20;
    select concat('年龄是',age,'身高是',height);
end$

if/else控制结构

if condition then 
  statement
else
end;

存储过程的括号里可以声明参数
语法是 [in/out/inout] 参数名 参数类型
给存储过程传递参数

create procedure p6(width int,height int)
begin
    declare area int default 0;
    if width > height then
        select '这个矩形比较宽';
    elseif width < height then
        select '这个矩形比较高';
    else
        select '这个矩形是个方的';
    end if;
    set area := width * height;
    select area;
end$

控制结构有三大类,顺序,选择,循环。
while的语法

WHILE expr_condition DO
    statement_list
END WHILE
create procedure p7()
begin
    declare total int default 0;
    declare num int default 0;
    while num < 101 do
        set total := total + num;
        set num := num + 1;
    end while;
    select total;
end$

in类型的参数,in代表input

create procedure p8(in n int)
begin
    declare total int default 0;
    declare num int default 0;
    while num < n do
        set num := num + 1;
        set total := total + num;
    end while;
    select total;
end$

out型

create procedure p9(in n int,out total int)
begin
    declare num int default 0;
    set total := 0;
    while num < n do
        set num := num + 1;
        set total := total + num;
    end while;
end$

调用

call p9(100,@sum)$
select @sum$

inout类型
CASE,LOOP,IF,LEAVE,ITERATE,REPEAT,WHILE语句

猜你喜欢

转载自www.cnblogs.com/Manual-Linux/p/10217220.html