SQL存储过程、存储函数
生活随笔
收集整理的這篇文章主要介紹了
SQL存储过程、存储函数
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
概念:
存儲過程和函數:
存儲過程和函數是事先經過編譯并存儲在數據庫中的一SQL語句的集合
存儲過程和函數的好處:
存儲過程和函數的區別:
存儲過程:
語法:
/*DELIMITER該關鍵字用來聲明sql語句的分隔符,告訴MySQL該段命令已經結束!sql語句默認的分隔符是分號,但是有的時候我們需要一條功能sql語句中包含分號,但是并不作為結束標識。這個時候就可以使用DELIMITER來指定分隔符了! */ -- 修改分隔符為$ DELIMITER $ -- 標準語法 CREATE PROCEDURE 存儲過程名稱(參數...) BEGINsql語句; END$-- 修改分隔符為分號 DELIMITER ;-- 存儲過程從這里結束-- 調用存儲過程 CALL 存儲過程名稱(實際參數);數據準備:
-- 創建學生表 CREATE TABLE student(id INT PRIMARY KEY AUTO_INCREMENT, -- 學生idNAME VARCHAR(20), -- 學生姓名age INT, -- 學生年齡gender VARCHAR(5), -- 學生性別score INT -- 學生成績 ); -- 添加數據 INSERT INTO student VALUES (NULL,'張三',23,'男',95),(NULL,'李四',24,'男',98), (NULL,'王五',25,'女',100),(NULL,'趙六',26,'女',90);-- 按照性別進行分組,查詢每組學生的總成績。按照總成績的升序排序 SELECT gender,SUM(score) getSum FROM student GROUP BY gender ORDER BY getSum ASC;創建存儲過程:
-- 創建存儲過程 DELIMITER $ CREATE PROCEDURE stu_group() BEGINSELECT gender,SUM(score) getSum FROM student GROUP BY gender ORDER BY getSum ASC; END$ DELIMITER ;-- 調用存儲過程 CALL stu_group();存儲過程的查看和刪除:
-- 查詢數據庫中所有的存儲過程 標準語法 show procedure status;-- 查看創建時SQL語句 SHOW CREATE PROCEDURE stu_group;-- 刪除存儲過程標準語法 DROP PROCEDURE [IF EXISTS] 存儲過程名稱; DROP PROCEDURE IF EXISTS stu_group;變量的使用:
定義變量:
-- 標準語法 DECLARE 變量名 數據類型 [DEFAULT 默認值]; -- 注意: DECLARE定義的是局部變量,只能用在BEGIN END范圍之內DELIMITER $ CREATE PROCEDURE pro_test1 () BEGINDECLARE num INT DEFAULT 10;-- 定義變量SELECT num;-- 使用變量 END$ DELIMITER;CALL pro_test1 ();-- 調用變量賦值方式1:
-- 標準語法 SET 變量名 = 變量值;-- 定義字符串類型變量,并賦值 DELIMITER $CREATE PROCEDURE pro_test2() BEGINDECLARE NAME VARCHAR(10); -- 定義變量SET NAME = '存儲過程'; -- 為變量賦值SELECT NAME; -- 查詢變量 END$DELIMITER ;-- 調用pro_test2存儲過程 CALL pro_test2();變量賦值方式2:
-- 標準語法 SELECT 列名 INTO 變量名 FROM 表名 [WHERE 條件];-- 定義兩個int變量,用于存儲男女同學的總分數 DELIMITER $CREATE PROCEDURE pro_test3() BEGINDECLARE men,women INT; -- 定義變量SELECT SUM(score) INTO men FROM student WHERE gender='男'; -- 計算男同學總分數賦值給menSELECT SUM(score) INTO women FROM student WHERE gender='女'; -- 計算女同學總分數賦值給womenSELECT men,women; -- 查詢變量 END$DELIMITER ;-- 調用pro_test3存儲過程 CALL pro_test3();if語句的使用:
-- 標準語法 IF 判斷條件1 THEN 執行的sql語句1; [ELSEIF 判斷條件2 THEN 執行的sql語句2;] ... [ELSE 執行的sql語句n;] END IF;/*定義一個int變量,用于存儲班級總成績定義一個varchar變量,用于存儲分數描述根據總成績判斷:380分及以上 學習優秀320 ~ 380 學習不錯320以下 學習一般 */ DELIMITER $CREATE PROCEDURE pro_test4() BEGIN-- 定義總分數變量DECLARE total INT;-- 定義分數描述變量DECLARE description VARCHAR(10);-- 為總分數變量賦值SELECT SUM(score) INTO total FROM student;-- 判斷總分數IF total >= 380 THEN SET description = '學習優秀';ELSEIF total >= 320 AND total < 380 THEN SET description = '學習不錯';ELSE SET description = '學習一般';END IF;-- 查詢總成績和描述信息SELECT total,description; END$DELIMITER ;-- 調用pro_test4存儲過程 CALL pro_test4();參數的傳遞:
@變量名: 這種變量要在變量名稱前面加上“@”符號,叫做用戶會話變量,代表整個會話過程他都是有作用的,這個類似于全局變量一樣。
@@變量名: 這種在變量前加上 “@@” 符號, 叫做系統變量
語法:
DELIMITER $-- 標準語法 CREATE PROCEDURE 存儲過程名稱([IN|OUT|INOUT] 參數名 數據類型) BEGIN執行的sql語句; END$ /*IN:代表輸入參數,需要由調用者傳遞實際數據。默認的OUT:代表輸出參數,該參數可以作為返回值INOUT:代表既可以作為輸入參數,也可以作為輸出參數 */ DELIMITER ;輸入參數IN:
/*輸入總成績變量,代表學生總成績輸出分數描述變量,代表學生總成績的描述根據總成績判斷:380分及以上 學習優秀320 ~ 380 學習不錯320以下 學習一般 */ DELIMITER $CREATE PROCEDURE pro_test6(IN total INT,OUT description VARCHAR(10)) BEGIN-- 判斷總分數IF total >= 380 THEN SET description = '學習優秀';ELSEIF total >= 320 AND total < 380 THEN SET description = '學習不錯';ELSE SET description = '學習一般';END IF; END$DELIMITER ;-- 調用pro_test6存儲過程 CALL pro_test6(310,@description);-- 查詢總成績描述 SELECT @description;輸出參數:
/*輸入總成績變量,代表學生總成績輸出分數描述變量,代表學生總成績的描述根據總成績判斷:380分及以上 學習優秀320 ~ 380 學習不錯320以下 學習一般 */ DELIMITER $CREATE PROCEDURE pro_test6(IN total INT,OUT description VARCHAR(10)) BEGIN-- 判斷總分數IF total >= 380 THEN SET description = '學習優秀';ELSEIF total >= 320 AND total < 380 THEN SET description = '學習不錯';ELSE SET description = '學習一般';END IF; END$DELIMITER ;-- 調用pro_test6存儲過程 CALL pro_test6(310,@description);-- 查詢總成績描述 SELECT @description;case語句:
語法1:
-- 標準語法 CASE 表達式 WHEN 值1 THEN 執行sql語句1; [WHEN 值2 THEN 執行sql語句2;] ... [ELSE 執行sql語句n;] END CASE;語法2:
-- 標準語法 CASE WHEN 判斷條件1 THEN 執行sql語句1; [WHEN 判斷條件2 THEN 執行sql語句2;] ... [ELSE 執行sql語句n;] END CASE;演示:
/*輸入總成績變量,代表學生總成績定義一個varchar變量,用于存儲分數描述根據總成績判斷:380分及以上 學習優秀320 ~ 380 學習不錯320以下 學習一般 */ DELIMITER $CREATE PROCEDURE pro_test7(IN total INT) BEGIN-- 定義變量DECLARE description VARCHAR(10);-- 使用case判斷CASEWHEN total >= 380 THENSET description = '學習優秀';WHEN total >= 320 AND total < 380 THENSET description = '學習不錯';ELSE SET description = '學習一般';END CASE;-- 查詢分數描述信息SELECT description; END$DELIMITER ;-- 調用pro_test7存儲過程 CALL pro_test7(390); CALL pro_test7((SELECT SUM(score) FROM student));while循環:
語法:
-- 標準語法 初始化語句; WHILE 條件判斷語句 DO循環體語句;條件控制語句; END WHILE;演示:
/*計算1~100之間的偶數和 */ DELIMITER $CREATE PROCEDURE pro_test8() BEGIN-- 定義求和變量DECLARE result INT DEFAULT 0;-- 定義初始化變量DECLARE num INT DEFAULT 1;-- while循環WHILE num <= 100 DO-- 偶數判斷IF num%2=0 THENSET result = result + num; -- 累加END IF;-- 讓num+1SET num = num + 1; END WHILE;-- 查詢求和結果SELECT result; END$DELIMITER ;-- 調用pro_test8存儲過程 CALL pro_test8();repeat循環:
repeat循環是條件滿足則停止。while循環是條件滿足則執行
語法:
-- 標準語法 初始化語句; REPEAT循環體語句;條件控制語句;UNTIL 條件判斷語句 END REPEAT;-- 注意:repeat循環是條件滿足則停止。while循環是條件滿足則執行 -- UNTIL只能寫在最下面演示:
/*計算1~10之間的和 */ DELIMITER $CREATE PROCEDURE pro_test9() BEGIN-- 定義求和變量DECLARE result INT DEFAULT 0;-- 定義初始化變量DECLARE num INT DEFAULT 1;-- repeat循環REPEAT-- 累加SET result = result + num;-- 讓num+1SET num = num + 1;-- 停止循環UNTIL num>10END REPEAT;-- 查詢求和結果SELECT result; END$DELIMITER ;-- 調用pro_test9存儲過程 CALL pro_test9();loop循環:
loop可以實現簡單的循環,但是退出循環需要使用其他的語句來定義。可以使用leave語句完成!
如果不加退出循環的語句,那么就變成了死循環
語法:
-- 標準語法 初始化語句; [循環名稱:] LOOP條件判斷語句[LEAVE 循環名稱;]循環體語句;條件控制語句; END LOOP 循環名稱;-- 注意:loop可以實現簡單的循環,但是退出循環需要使用其他的語句來定義。我們可以使用leave語句完成! -- [循環名稱:] LOOP循環名稱要加 如果不加退出循環的語句,那么就變成了死循環。 /*計算1~10之間的和 */ DELIMITER $CREATE PROCEDURE pro_test10() BEGIN-- 定義求和變量DECLARE result INT DEFAULT 0;-- 定義初始化變量DECLARE num INT DEFAULT 1;-- loop循環l:LOOP-- 條件成立,停止循環IF num > 10 THENLEAVE l;END IF;-- 累加SET result = result + num;-- 讓num+1SET num = num + 1;END LOOP l;-- 查詢求和結果SELECT result; END$DELIMITER ;-- 調用pro_test10存儲過程 CALL pro_test10();游標:
- 游標可以遍歷返回的多行結果,每次拿到一整行數據
- 在存儲過程和函數中可以使用游標對結果集進行循環的處理
- 簡單來說游標就類似于集合的迭代器遍歷
- MySQL中的游標只能用在存儲過程和函數中
| 創建游標 | DECLARE 游標名稱 CURSOR FOR 查詢sql語句; |
| 打開游標 | OPEN 游標名稱; |
| 使用游標獲取數據 | FETCH 游標名稱 INTO 變量名1,變量名2,…; |
| 關閉游標 | CLOSE 游標名稱; |
演示:
-- 創建stu_score表 CREATE TABLE stu_score(id INT PRIMARY KEY AUTO_INCREMENT,score INT );/*將student表中所有的成績保存到stu_score表中 */ DELIMITER $CREATE PROCEDURE pro_test11() BEGIN-- 定義成績變量DECLARE s_score INT;-- 創建游標,查詢所有學生成績數據DECLARE stu_result CURSOR FOR SELECT score FROM student;-- 開啟游標OPEN stu_result;-- 使用游標,遍歷結果,拿到第1行數據FETCH stu_result INTO s_score;-- 將數據保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);-- 使用游標,遍歷結果,拿到第2行數據FETCH stu_result INTO s_score;-- 將數據保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);-- 使用游標,遍歷結果,拿到第3行數據FETCH stu_result INTO s_score;-- 將數據保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);-- 使用游標,遍歷結果,拿到第4行數據FETCH stu_result INTO s_score;-- 將數據保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);-- 關閉游標CLOSE stu_result; END$DELIMITER ;-- 調用pro_test11存儲過程 CALL pro_test11();-- 查詢stu_score表 SELECT * FROM stu_score;-- =========================================================== /*出現的問題:student表中一共有4條數據,我們在游標遍歷了4次,沒有問題!但是在游標中多遍歷幾次呢?就會出現問題 */ DELIMITER $CREATE PROCEDURE pro_test11() BEGIN-- 定義成績變量DECLARE s_score INT;-- 創建游標,查詢所有學生成績數據DECLARE stu_result CURSOR FOR SELECT score FROM student;-- 開啟游標OPEN stu_result;-- 使用游標,遍歷結果,拿到第1行數據FETCH stu_result INTO s_score;-- 將數據保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);-- 使用游標,遍歷結果,拿到第2行數據FETCH stu_result INTO s_score;-- 將數據保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);-- 使用游標,遍歷結果,拿到第3行數據FETCH stu_result INTO s_score;-- 將數據保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);-- 使用游標,遍歷結果,拿到第4行數據FETCH stu_result INTO s_score;-- 將數據保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);-- 使用游標,遍歷結果,拿到第5行數據FETCH stu_result INTO s_score;-- 將數據保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);-- 關閉游標CLOSE stu_result; END$DELIMITER ;-- 調用pro_test11存儲過程 CALL pro_test11();-- 查詢stu_score表,雖然數據正確,但是在執行存儲過程時會報錯 SELECT * FROM stu_score;游標的優化使用(配合循環使用)
/*當游標結束后,會觸發游標結束事件。我們可以通過這一特性來完成循環操作加標記思想:1.定義一個變量,默認值為0(意味著有數據)2.當游標結束后,將變量值改為1(意味著沒有數據了) */ -- 1.定義一個變量,默認值為0(意味著有數據) DECLARE flag INT DEFAULT 0; -- 2.當游標結束后,將變量值改為1(意味著沒有數據了) DECLARE EXIT HANDLER FOR NOT FOUND SET flag = 1;/*將student表中所有的成績保存到stu_score表中 */ DELIMITER $CREATE PROCEDURE pro_test12() BEGIN-- 定義成績變量DECLARE s_score INT;-- 定義標記變量DECLARE flag INT DEFAULT 0;-- 創建游標,查詢所有學生成績數據DECLARE stu_result CURSOR FOR SELECT score FROM student;-- 游標結束后,將標記變量改為1,判斷,如果沒有數據就把flag改為1DECLARE EXIT HANDLER FOR NOT FOUND SET flag = 1;-- 開啟游標OPEN stu_result;-- 循環使用游標REPEAT-- 使用游標,遍歷結果,拿到數據FETCH stu_result INTO s_score;-- 將數據保存到stu_score表中INSERT INTO stu_score VALUES (NULL,s_score);UNTIL flag=1END REPEAT;-- 關閉游標CLOSE stu_result; END$DELIMITER ;-- 調用pro_test12存儲過程 CALL pro_test12();-- 查詢stu_score表 SELECT * FROM stu_score;存儲函數:
存儲函數和存儲過程是非常相似的。存儲函數可以做的事情,存儲過程也可以做到!
存儲函數有返回值,存儲過程沒有返回值(參數的out其實也相當于是返回數據了)
創建存儲函數
DELIMITER $-- 標準語法 CREATE FUNCTION 函數名稱([參數 數據類型]) RETURNS 返回值類型 BEGIN執行的sql語句;RETURN 結果; END$DELIMITER ;調用存儲函數
-- 標準語法 SELECT 函數名稱(實際參數);刪除存儲函數
-- 標準語法 DROP FUNCTION 函數名稱;演示:
/*定義存儲函數,獲取學生表中成績大于95分的學生數量 */ DELIMITER $CREATE FUNCTION fun_test1() RETURNS INT BEGIN-- 定義統計變量DECLARE result INT;-- 查詢成績大于95分的學生數量,給統計變量賦值SELECT COUNT(*) INTO result FROM student WHERE score > 95;-- 返回統計結果RETURN result; END$DELIMITER ;-- 調用fun_test1存儲函數 SELECT fun_test1();-- 刪除存儲函數 DROP FUNCTION fun_test1;總結
以上是生活随笔為你收集整理的SQL存储过程、存储函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: humanize时间库使用及汉化
- 下一篇: linux下查看mysql配置文件位置