Mysql存储过程和存储函数
存儲過程和存儲函數
- 前言
- 存儲過程的相關操作
- 創建
- 調用
- 查看
- 刪除
- 語法
- 變量的定義與賦值
- if條件判斷
- 參數
- case結構
- while循環
- repeat循環結構
- loop語句
- leave語句
- 游標/光標
- 存儲函數
前言
存儲過程和函數是 事先經過編譯并存儲在數據庫中的一段 SQL 語句的集合,調用存儲過程和函數可以簡化應用開 發人員的很多工作,減少數據在數據庫和應用服務器之間的傳輸,對于提高數據處理的效率是有好處的。
Mysql是從5.0版本開始支持存儲過程和函數的。
存儲過程和函數的區別在于函數必須有返回值,而存儲過程沒有。
函數 : 是一個有返回值的過程 ;
過程 : 是一個沒有返回值的函數 ;
對于存儲過程或函數在進行操作的時候,需要首先確認用戶是否具有相應的權限。
查看當前root用戶的權限:
查看普通用戶的權限:
SHOW GRANTS FOR 普通用戶名;
和存儲過程有關的權限有三種:
ALTER ROUTINE 編輯或刪除存儲過程
CREATE ROUTINE 建立存儲過程
EXECUTE 運行存儲過程
DELIMITER 來聲明SQL語句的分隔符 , 告訴 MySQL 解釋器,該段命令是否已經結束了,mysql是否可以執行了。
默認情況下,delimiter是分號;。在命令行客戶端中,如果有一行命令以分號結束,那么回車后,mysql將會執行該命令。
存儲過程的相關操作
創建
CREATE PROCEDURE procedure_name ([proc_parameter[,...]]) begin -- SQL語句 end ;示例:
delimiter $create procedure pro_test1() begin select 'Hello Mysql' ; end$ delimiter ;調用
call procedure_name() ;查看
-- 查詢db_name數據庫中的所有的存儲過程 select name from mysql.proc where db='db_name'; -- 查詢存儲過程的狀態信息 show procedure status; -- 查詢某個存儲過程的定義 show create procedure test.pro_test1 \G;如:
刪除
DROP PROCEDURE [IF EXISTS] sp_name ;語法
存儲過程是可以編程的,意味著可以使用變量,表達式,控制結構等來完成比較復雜的功能。
變量的定義與賦值
通過 DECLARE 可以定義一個局部變量,該變量的作用范圍只能在 BEGIN…END 塊中
示例:
delimiter $create procedure pro_test2() begin declare num int default 5; select num+ 10; end$delimiter ;直接賦值使用 SET,可以賦常量或者賦表達式,具體語法如下:
示例:
DELIMITER $ CREATE PROCEDURE pro_test3() BEGIN DECLARE NAME VARCHAR(20); SET NAME = 'MYSQL'; SELECT NAME ; END$ DELIMITER ;也可以通過select … into 方式進行賦值操作 :
示例:
if條件判斷
語法結構:
if search_condition then statement_list[elseif search_condition then statement_list] ... [else statement_list] end if;示例:
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 ;參數
create procedure procedure_name([in/out/inout] 參數名 參數類型) ...IN : 該參數可以作為輸入,也就是需要調用方傳入值 , 默認 OUT: 該參數作為輸出,也就是該參數可以作為返回值 INOUT: 既可以作為輸入參數,也可以作為輸出參數示例:
create procedure pro_test5(in height int , out description varchar(100)) begin if height >= 180 then set description='身材高挑'; elseif height >= 170 and height < 180 then set description='標準身材'; else set description='一般身材'; end if; end$調用:
call pro_test5(168, @description)$select @description$@description : 這種變量要在變量名稱前面加上“@”符號,叫做用戶會話變量,代表整個會話過程他都是有作用 的,這個類似于全局變量一樣。
@@global.sort_bu?er_size : 這種在變量前加上 “@@” 符號, 叫做 系統變量
case結構
方式一 : CASE case_valueWHEN when_value THEN statement_list[WHEN when_value THEN statement_list] ...[ELSE statement_list]END CASE;方式二 : CASEWHEN search_condition THEN statement_list[WHEN search_condition THEN statement_list] ...[ELSE statement_list]END CASE;示例:給定一個月份計算出所在季度
delimiter $--方式二 create procedure pro_test9(month int) begindeclare 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 ;while循環
語法結構:
while search_condition dostatement_listend while;示例:求1到n的累加和
delimiter $create procedure pro_test8(n int) begindeclare total int default 0;declare num int default 1;while num<=n doset total = total + num;set num = num + 1;end while;select total; end$delimiter ;repeat循環結構
repeat是有條件的循環控制語句, 當滿足條件的時候退出循環; while 是滿足條件才執行,repeat 是滿足條件就退出循環。
語法結構:
示例:計算從1到n的累加值
delimiter $create procedure pro_test10(n int) begindeclare total int default 0;repeat set total = total + n;set n = n - 1;until n=0 end repeat;select total ;end$delimiter ;loop語句
LOOP 實現簡單的循環,退出循環的條件需要使用其他的語句定義,通常可以使用 LEAVE 語句實現,具體語法如下:
[begin_label:] LOOPstatement_listEND LOOP [end_label]如果不在 statement_list 中增加退出循環的語句,那么 LOOP 語句可以用來實現簡單的死循環。
begin_label:是定義的loop循環的標簽/名稱。
leave語句
用來從標注的流程構造中退出,通常和 BEGIN … END 或者循環一起使用。下面是一個使用 LOOP 和 LEAVE 的簡單例子 , 退出循環:
delimiter $CREATE PROCEDURE pro_test11(n int) BEGINdeclare total int default 0;ins: LOOPIF n <= 0 thenleave ins;END IF;set total = total + n;set n = n - 1;END LOOP ins;select total; END$delimiter ;游標/光標
游標是用來存儲查詢結果集的數據類型 , 在存儲過程和函數中可以使用光標對結果集進行循環的處理。光標的使用包括光標的聲明、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 ;示例:
初始化腳本:
創建存儲過程:(該存儲過程是通過游標保存查詢的結果集)
-- 查詢emp表中數據, 并逐行獲取進行展示 create procedure pro_test11() begindeclare 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() beginDECLARE 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;repeatfetch emp_result into id , name , age , salary;select concat('id為',id, ', name 為' ,name , ', age為 ' ,age , ', 薪水為: ', salary);until has_data = 0end repeat;close emp_result; end$DELIMITER ;我們前面給數據庫中插入了4條數據,但是我們編寫的存儲過程中抓取了5個數據,所以在調用存儲過程的時候會將4條數據抓取完后報錯。
調用:
我們一般在使用游標抓取數據的時候可能不知道數據的多少或者數據量過多沒法一條一條進行抓取,因此我們可以采用循環來實現抓取全部數據。
調用:
存儲函數
語法結構:
CREATE FUNCTION function_name([param type ... ]) RETURNS type BEGIN... END;示例:
--創建數據表 CREATE TABLE `city` (`city_id` int(11) NOT NULL AUTO_INCREMENT,`city_name` varchar(50) NOT NULL,`country_id` int(11) NOT NULL,PRIMARY KEY (`city_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE `country` (`country_id` int(11) NOT NULL AUTO_INCREMENT,`country_name` varchar(100) NOT NULL,PRIMARY KEY (`country_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;insert into `city` (`city_id`, `city_name`, `country_id`) values(1,'西安',1); insert into `city` (`city_id`, `city_name`, `country_id`) values(2,'NewYork',2); insert into `city` (`city_id`, `city_name`, `country_id`) values(3,'北京',1); insert into `city` (`city_id`, `city_name`, `country_id`) values(4,'上海',1);insert into `country` (`country_id`, `country_name`) values(1,'China'); insert into `country` (`country_id`, `country_name`) values(2,'America'); insert into `country` (`country_id`, `country_name`) values(3,'Japan'); insert into `country` (`country_id`, `country_name`) values(4,'UK');delimiter $create function count_city(countryId int) returns int begindeclare cnum int ;select count(*) into cnum from city where country_id = countryId;return cnum; end$delimiter ;調用:
select count_city(1);
如果在創建存儲函數的時候遇到了報錯請參考我的這篇文章
感謝🤭
總結
以上是生活随笔為你收集整理的Mysql存储过程和存储函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手机定位服务在哪里打开(手机游戏下载)
- 下一篇: linux cmake编译源码,linu