日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

SQL存储过程、存储函数

發布時間:2023/12/10 数据库 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SQL存储过程、存储函数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

概念:

存儲過程和函數:

存儲過程和函數是事先經過編譯并存儲在數據庫中的一SQL語句的集合

存儲過程和函數的好處:

  • 存儲過程和函數可以重復使用,減輕開發人員的工作量。類似于java中方法可以多次調用
  • 減少網絡流量,存儲過程和函數位于服務器上,調用的時候只需要傳遞名稱和參數即可
  • 減少數據在數據庫和應用服務器之間的傳輸,可以提高數據處理的效率
  • 將一些業務邏輯在數據庫層面來實現,可以減少代碼層面的業務處理
  • 存儲過程和函數的區別:

  • 函數必須有返回值
  • 存儲過程沒有返回值
  • 存儲過程:

    語法:
    /*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 表達式 WHEN1 THEN 執行sql語句1; [WHEN2 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存储过程、存储函数的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。