1. 程式人生 > >MySQL學習(十六)

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語句