Mysql底層知識進階-語法

4.6 語法(其實和寫c,沒啥區別)

存儲過程是可以編程的,意味着可以使用變量,表達式,控制結構 , 來完成比較複雜的功能。

4.6.1 變量

  • DECLARE(聲明變量)

    通過 DECLARE 可以定義一個局部變量,該變量的作用範圍只能在 BEGIN…END 塊中。

DECLARE var_name[,...] type [DEFAULT value]

示例 :

 delimiter $

 create procedure pro_test2() 
 begin 
 	declare num int default 5;
 	select num+ 10; 
 end$

 delimiter ; 
  • SET(給變量賦值)

直接賦值使用 SET,可以賦常量或者賦表達式,具體語法如下:

SET var_name = expr [, var_name = expr] ...

示例 :

 DELIMITER $
  
  CREATE  PROCEDURE pro_test3()
  BEGIN
  	DECLARE NAME VARCHAR(20);
  	SET NAME = 'MYSQL';
  	SELECT NAME ;
  END$
  
  DELIMITER ;

也可以通過select ... into 方式進行賦值操作 :

DELIMITER $

CREATE  PROCEDURE pro_test5()
BEGIN
	declare  countnum int;
	select count(*) into countnum from city;
	select countnum;
END$

DELIMITER ;

4.6.2 if條件判斷

語法結構 :

if search_condition then statement_list

	[elseif search_condition then statement_list] ...
	
	[else statement_list]
	
end if;

舉個例子,有個小需求:

根據定義的身高變量,判定當前身高的所屬的身材類型 

	180 及以上 ----------> 身材高挑

	170 - 180  ---------> 標準身材

	170 以下  ----------> 一般身材
delimiter $

create procedure pro_test6()
begin
  declare  height  int  default  175; 
  declare  description  varchar(50);
  
  if  height >= 180  then
    set description = '身材高挑';
  elseif height >= 170 and height < 180  then
    set description = '標準身材';
  else
    set description = '一般身材';
  end if;
  
  select description ;
end$

delimiter ;

調用結果爲 :

4.6.3 傳遞參數

現在我得需求變化了,我想要動態傳入height的值,然後你給我做判斷,這時候,就用到了傳遞參數。

語法格式 :

create procedure procedure_name([in/out/inout] 參數名   參數類型)
...


IN :   該參數可以作爲輸入,也就是需要調用方傳入值 , 默認
OUT:   該參數作爲輸出,也就是該參數可以作爲返回值
INOUT: 既可以作爲輸入參數,也可以作爲輸出參數

IN - 輸入

需求 :

根據定義的身高變量,判定當前身高的所屬的身材類型 

示例 :

delimiter $

create procedure pro_test5(in height int)
begin
    declare description varchar(50) default '';
  if height >= 180 then
    set description='身材高挑';
  elseif height >= 170 and height < 180 then
    set description='標準身材';
  else
    set description='一般身材';
  end if;
  select concat('身高 ', height , '對應的身材類型爲:',description);
end$

delimiter ;

調用:

call pro_test5(168, @description)$

select @description$

小知識 

@description : 這種變量要在變量名稱前面加上“@”符號,叫做用戶會話變量,代表整個會話過程他都是有作用的,這個類似於全局變量一樣。

@@global.sort_buffer_size : 這種在變量前加上 "@@" 符號, 叫做 系統變量

 

4.6.4 case結構

語法結構 :

方式一 : 

CASE case_value

  WHEN when_value THEN statement_list
  
  [WHEN when_value THEN statement_list] ...
  
  [ELSE statement_list]
  
END CASE;


方式二 : 

CASE

  WHEN search_condition THEN statement_list
  
  [WHEN search_condition THEN statement_list] ...
  
  [ELSE statement_list]
  
END CASE;

需求:

給定一個月份, 然後計算出所在的季度

示例 :

delimiter $


create procedure pro_test9(month int)
begin
  declare result varchar(20);
  case 
    when month >= 1 and month <=3 then 
      set result = '第一季度';
    when month >= 4 and month <=6 then 
      set result = '第二季度';
    when month >= 7 and month <=9 then 
      set result = '第三季度';
    when month >= 10 and month <=12 then 
      set result = '第四季度';
  end case;
  
  select concat('您輸入的月份爲 :', month , ' , 該月份爲 : ' , result) as content ;
  
end$


delimiter ;

4.6.5 while循環

語法結構:

while search_condition do

	statement_list
	
end while;

需求:

計算從1加到n的值

示例 :

delimiter $

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

delimiter ;

4.6.6 repeat結構

有條件的循環控制語句, 當滿足條件的時候退出循環 。while 是滿足條件才執行,repeat 是滿足條件就退出循環。

語法結構 :

REPEAT

  statement_list

  UNTIL search_condition

END REPEAT;

需求:

計算從1加到n的值

示例 :

delimiter $

create procedure pro_test10(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$


delimiter ;

4.6.7 loop語句(與leave語句配合)

LOOP 實現簡單的循環,退出循環的條件需要使用其他的語句定義,通常可以使用 LEAVE 語句實現,具體語法如下:

[begin_label:] LOOP

  statement_list

END LOOP [end_label]

如果不在 statement_list 中增加退出循環的語句,那麼 LOOP 語句可以用來實現簡單的死循環。

4.6.8 leave語句

用來從標註的流程構造中退出,通常和 BEGIN ... END 或者循環一起使用。下面是一個使用 LOOP 和 LEAVE 的簡單例子 , 退出循環:

delimiter $

CREATE PROCEDURE pro_test11(n int)
BEGIN
  declare total int default 0;
  
  ins: LOOP              #ins 爲這個loop的別名
    
    IF n <= 0 then
      leave ins;
    END IF;
    
    set total = total + n;
    set n = n - 1;
  	
  END LOOP ins;
  
  select total;
END$

delimiter ;

4.6.9 遊標/光標

遊標是用來存儲查詢結果集的數據類型 , 在存儲過程和函數中可以使用光標對結果集進行循環的處理。光標的使用包括光標的聲明、OPEN、FETCH 和 CLOSE,其語法分別如下。

聲明光標:

DECLARE cursor_name CURSOR FOR select_statement ;

OPEN 光標:

OPEN cursor_name ;

FETCH 光標:

FETCH cursor_name INTO var_name [, var_name] ...

CLOSE 光標:

CLOSE cursor_name ;

示例 :

初始化腳本:

create table emp(
  id int(11) not null auto_increment ,
  name varchar(50) not null comment '姓名',
  age int(11) comment '年齡',
  salary int(11) comment '薪水',
  primary key(`id`)
)engine=innodb default charset=utf8 ;

insert into emp(id,name,age,salary) values(null,'金毛獅王',55,3800),(null,'白眉鷹王',60,4000),(null,'青翼蝠王',38,2800),(null,'紫衫龍王',42,1800);
-- 查詢emp表中數據, 並逐行獲取進行展示
create procedure pro_test11()
begin
  declare e_id int(11);
  declare e_name varchar(50);
  declare e_age int(11);
  declare e_salary int(11);
  declare emp_result cursor for select * from emp;
  
  open emp_result;
  
  fetch emp_result into e_id,e_name,e_age,e_salary;
  select concat('id=',e_id , ', name=',e_name, ', age=', e_age, ', 薪資爲: ',e_salary);
  
  fetch emp_result into e_id,e_name,e_age,e_salary;
  select concat('id=',e_id , ', name=',e_name, ', age=', e_age, ', 薪資爲: ',e_salary);
  
  fetch emp_result into e_id,e_name,e_age,e_salary;
  select concat('id=',e_id , ', name=',e_name, ', age=', e_age, ', 薪資爲: ',e_salary);
  
  fetch emp_result into e_id,e_name,e_age,e_salary;
  select concat('id=',e_id , ', name=',e_name, ', age=', e_age, ', 薪資爲: ',e_salary);
  
  fetch emp_result into e_id,e_name,e_age,e_salary;
  select concat('id=',e_id , ', name=',e_name, ', age=', e_age, ', 薪資爲: ',e_salary);
  
  close emp_result;
end$

通過循環結構 , 獲取遊標中的數據 :

DELIMITER $

create procedure pro_test12()
begin
  DECLARE id int(11);
  DECLARE name varchar(50);
  DECLARE age int(11);
  DECLARE salary int(11);
  DECLARE has_data int default 1;
  
  DECLARE emp_result CURSOR FOR select * from emp;
  DECLARE EXIT HANDLER FOR NOT FOUND set has_data = 0;
  
  open emp_result;
  
  repeat
    fetch emp_result into id , name , age , salary;
    select concat('id爲',id, ', name 爲' ,name , ', age爲 ' ,age , ', 薪水爲: ', salary);
    until has_data = 0
  end repeat;
  
  close emp_result;
end$

DELIMITER ; 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章