過程:
封裝了若干條語句.調用時,這些封裝體執行.
函數:
是一個有返回值的過程.
過程是沒有返回值的函數
存儲過程:
把此過程存儲在數據庫中,因此稱為存儲過程
存儲過程語法
# 創建語法:
create procedure procedureName()
begin
-- sql語句
end$
# 刪除存儲過程
drop procedure procedureName;
# 查看已有的procedure
show procedure status;
# 調用存儲過程:
call procedureName();
存儲過程1--創建簡單的存儲過程
# eg:
create procedure p1()
begin
select * from tableName;
end$
存儲過程2--引入變量
# 存儲過稱是可以編程的,意味著可以使用變量,表達式,控制結構
# eg:
create procedure p2()
begin
declare age int default 18;
declare height int default 180;
select concat('年齡是',age,'身高是',height);
end$
存儲過程3--變量運算
# 存儲過稱中,變量可以在sql語句中合法的運算,如+-*/,注意運算的結果是如何賦值給變量
# 語法--set 變量名 := expression
# eg:
create procedure p3()
begin
declare age int default 18;
declare height int default 180;
set age := age + 20;
select concat('20年后年齡是',age,'身高是',height);
end$
存儲過稱4--控制結構(if/else)
# 語法:
if
conditon
then
statement
else
statement
end;
# eg:
create procedure p4()
begin
declare age int default 18;
if age >= 18 then
select '已成年';
else
select '未成年';
end if;
end$
存儲過稱5--控制結構2(while)
# 三種控制結構:
順序,選擇,循環
# eg: 求1-100的和
create procedure p5()
begin
declare total int default 0;
declare num int default 0;
while num <= 100 do
set total := total + num;
set num := num + 1;
end while;
select total;
end$
存儲過稱6--控制結構3(case)
# 用if/else也能實現同樣的效果
# eg:
create procedure p6()
begin
declare pos int default 0;
set pos := floor(5*rand());
case pos
when 1 then select 'fly';
when 2 then select 'sea';
else select 'run';
end case;
end$
存儲過稱7--控制結構4(repeat)
# 用while也能實現同樣的效果
# eg:
create procedure p7()
begin
declare total int default 0;
declare i int default 0;
repeat
set i := i+1;
set total := total + i;
until i>=100
end repeat;
select total;
end$
存儲過稱8--傳參
# 存儲過程的括號里,可以聲明參數,
# 語法:
[in/out/inout] 參數名 參數類型,不寫時,默認為in
# 調用:
call p8(3,4)
# eg:
create procedure p8(width int , height int)
begin
select concat('你的面積是',width * height) as area;
if width > height then
select '寬大于高';
elseif width < height then
select '寬小于高';
else
select '寬等于高';
end if;
end$
存儲過稱9--in型參數
# 存儲過程中可以接收到這個參數
# eg: 求1-n的和
create procedure p9(in n int)
begin
declare total int default 0;
declare num int default 0;
while num <= n do
set total := total + num;
set num := num + 1;
end while;
select total;
end$
存儲過稱10--out型參數
# 將存儲過程中值輸出
# 調用:
call p10(100,@argsName)
# eg: 求1-n的和
create procedure p10(in n int,out total int)
begin
declare num int default 0;
set total := 0;
while num <= n do
set total := total + num;
set num := num + 1;
end while;
select total;
end$
# 此處執行完成后,輸入select @argsName即可得到對應的結果
存儲過稱11--inout型參數
# 調用:
set @age = 18
call p11(@age)
# eg:
create procedure p11(inout age int)
begin
set age := 1;
set age := age + 20;
end$
存儲過稱12--cursor 游標
# 一條sql,對應N條資源,取出資源的接口/句柄,就說游標
# 沿著游標,可以一次取出一行
# eg:
create procedure p12()
begin
declare row_gid int;
declare row_num int;
declare row_name varchar(20);
-- 這種方法不推薦使用
-- 定義一個游標
declare cursorName cursor for select gid,num,name from goods;
open cursorName;
-- 將顯示的第一行值賦予對應的變量
fetch cursorName into row_gid,row_num,row_name;
select row_gid,row_num,row_name;
-- 將顯示的第二行值賦予對應的變量
fetch cursorName into row_gid,row_num,row_name;
select row_gid,row_num,row_name;
-- 將顯示的第三行值賦予對應的變量(如果只有兩條數據,賦值三次會報錯)
fetch cursorName into row_gid,row_num,row_name;
select row_gid,row_num,row_name;
close cursorName;
end$
存儲過稱13--cursor 游標(推薦使用)
# eg:
create procedure p13()
begin
declare row_gid int;
declare row_num int;
declare row_name varchar(20);
declare i int default 0;
-- 定義一個變量,用來計算顯示了幾條數據
declare cnt int default 0;
-- 定義一個游標
declare cursorName cursor for select gid,num,name from goods;
select count(*) into cnt from goods;
open cursorName;
repeat
set i := i +1;
fetch cursorName into row_gid,row_num,row_name;
select row_gid,row_num,row_name;
until i >= cnt
end repeat;
close cursorName;
end$
存儲過稱14--越界標志(continue handler for not found)
# 在MySQL cursor中,可以declare continue handler來操作一個越界標志
# 語法: declare continue handler for not found 語句;
# 表中只有三條數據,但是下面的代碼執行后 ,會取出四行,最后一行顯示兩次
# 代碼中有邏輯錯誤,分析:
當第四次執行 repeat 時,fetch-->沒有數據,觸發越界標志中的not found-->set you := 0-->continue-->執行fetch后面的sql語句(select row_gid,row_num,row_name;)-->所以,最后一行被取出兩次
# eg:
create procedure p14()
begin
declare row_gid int;
declare row_num int;
declare row_name varchar(20);
declare you int default 1;
-- 定義一個游標
declare cursorName cursor for select gid,num,name from goods;
declare continue handler for not found set you := 0;
open cursorName;
repeat
fetch cursorName into row_gid,row_num,row_name;
select row_gid,row_num,row_name;
until you = 0
end repeat;
close cursorName;
end$
存儲過稱15--越界標志(exit handler for not found)
# 越界標志解決邏輯錯誤(不完善,沒考慮到表為空的情況)
# 引入另一種越界標志:declare exit handler for not found 語句;
# eg:
create procedure p15()
begin
declare row_gid int;
declare row_num int;
declare row_name varchar(20);
declare you int default 1;
-- 定義一個游標
declare cursorName cursor for select gid,num,name from goods;
declare exit handler for not found set you := 0;
open cursorName;
repeat
fetch cursorName into row_gid,row_num,row_name;
select row_gid,row_num,row_name;
until you = 0
end repeat;
close cursorName;
end$
存儲過稱16--越界標志(undo handler)
# 除以上兩種越界標志(continue,exit)外,還有undo handler
# continue是觸發后,后面的語句繼續執行
# exit是觸發后,后面的語句不再執行
# undo是觸發后,前面的語句撤銷(MySQL暫不支持)
# 不改變越界標志,解決邏輯錯誤(完善)
# eg:
create procedure p16()
begin
declare row_gid int;
declare row_num int;
declare row_name varchar(20);
declare you int default 1;
-- 定義一個游標
declare cursorName cursor for select gid,num,name from goods;
declare exit handler for not found set you := 0;
open cursorName;
-- 1: 先取出一行數據,如果取出,則 not found未觸發,
fetch cursorName into row_gid,row_num,row_name;
repeat
-- 2: 執行顯示語句
select row_gid,row_num,row_name;
-- 3: 在進行fetch如果取不到,觸發continue越界標志,繼續向下執行,
-- 下面沒有sql語句,所以不會再顯示
fetch cursorName into row_gid,row_num,row_name;
until you = 0
end repeat;
close cursorName;
end$