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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

MySQL入门系列:存储程序(二)之存储函数简介

發布時間:2025/6/17 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL入门系列:存储程序(二)之存储函数简介 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

存儲例程

存儲例程是存儲程序的一種類型,本質上也是封裝了一些可執行的語句,只不過它的調用方式是:需要手動去調用!存儲例程又可以分為存儲函數和存儲過程,下邊我們詳細嘮叨這兩個家伙。

存儲函數

創建存儲函數

存儲函數其實就是一種函數,只不過在這個函數里可以執行命令語句而已。函數的概念大家都應該不陌生,它可以把處理某個問題的過程封裝起來,之后我們直接調用函數就可以去解決同樣的問題了,簡單方便又環保。MySQL中定義存儲函數的語句如下:

CREATE FUNCTION 存儲函數名稱([參數列表]) RETURNS 返回值類型 BEGIN函數體內容 END 復制代碼

從這里我們可以看出,定義一個存儲函數需要指定函數名稱、參數列表、返回值類型以及函數體內容,如果該函數不需要參數,那參數列表可以被省略,函數體內容可以包括一條或多條語句,每條語句都要以分號;結尾。里邊的制表符和換行僅僅是為了好看,如果你覺得煩,完全可以用空格代替! 光看定義理解的不深刻,我們先寫一個存儲函數開開眼:

mysql> delimiter $ mysql> CREATE FUNCTION avg_score(s VARCHAR(100))-> RETURNS DOUBLE-> BEGIN-> RETURN (SELECT AVG(score) FROM student_score WHERE subject = s);-> END $ Query OK, 0 rows affected (0.00 sec)mysql> delimiter ; 復制代碼

我們定義了一個名叫avg_score的函數,它接收一個VARCHAR(100)類型的參數,聲明的返回值類型是DOUBLE,需要注意的是,我們在RETURN語句后邊寫了一個SELECT語句,表明這個函數的最后返回結果就是根據這個查詢語句產生的,也就是返回了指定科目的平均成績。

存儲函數的調用

我們自定義的函數和系統內置函數的使用方式是一樣的,都是在函數名后加小括號()表示函數調用,有參數的函數調用可以把參數寫到小括號里邊。函數調用可以作為查詢對象或者搜索條件,或者和別的操作數一起組成更復雜的表達式,我們現在來調用一下剛剛寫好的這個函數吧:

mysql> SELECT avg_score('母豬的產后護理'); +------------------------------------+ | avg_score('母豬的產后護理') | +------------------------------------+ | 73 | +------------------------------------+ 1 row in set (0.00 sec)mysql> SELECT avg_score('論薩達姆的戰爭準備'); +------------------------------------------+ | avg_score('論薩達姆的戰爭準備') | +------------------------------------------+ | 73.25 | +------------------------------------------+ 1 row in set (0.00 sec)mysql> 復制代碼

這樣調用函數就比我們直接寫兩個又臭又長的查詢語句簡單多了。

查看和刪除存儲函數

如果我們想查看我們已經定義了多少個存儲函數,可以使用下邊這個語句:

SHOW FUNCTION STATUS [LIKE 需要匹配的函數名] 復制代碼

由于這個命令得到的結果太多,我們就不演示了哈,自己試試。

如果我們想查看某個函數的具體定義,可以使用這個語句:

SHOW CREATE FUNCTION 函數名 復制代碼

比如這樣:

mysql> SHOW CREATE FUNCTION avg_score\G *************************** 1. row ***************************Function: avg_scoresql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTIONCreate Function: CREATE DEFINER=`root`@`localhost` FUNCTION `avg_score`(s VARCHAR(100)) RETURNS double BEGINRETURN (SELECT AVG(score) FROM student_score WHERE subject = s);END character_set_client: utf8 collation_connection: utf8_general_ciDatabase Collation: utf8_general_ci 1 row in set (0.01 sec)mysql> 復制代碼

忽略結果中我們看不懂的那些東東,后邊都會詳細嘮叨的,現在主要聚焦在這個函數的定義處。

如果想刪除某個存儲函數,使用這個語句:

DROP FUNCTION 函數名 復制代碼

比如我們來刪掉avg_score這個函數:

mysql> DROP FUNCTION avg_score; Query OK, 0 rows affected (0.00 sec)mysql> 復制代碼

什么?你以為到這里存儲函數就嘮叨完了么?寫完是不可能的,這輩子都不可能寫完的!到現在為止我們只是勾勒出一個存儲函數的大致輪廓,下邊我們來詳細說一下MySQL定義函數體時支持的一些語句。

在函數體中定義變量

我們在前邊說過在命令行(黑框框)中自定義變量的方式,它可以不用聲明就為變量賦值(也就是調用SET語句)。而在函數體中使用變量前必須先聲明這個變量,聲明方式如下:

DECLARE 變量名 數據類型 [DEFAULT 默認值]; 復制代碼

需要特別留心的是,函數體中的變量名不允許加@前綴,這一點和黑框框中定義變量的方式是截然不同的,特別注意一下。在聲明了這個變量之后,才可以使用它:

mysql> delimiter $; mysql> CREATE FUNCTION var_demo() -> RETURNS INT -> BEGIN -> DECLARE c INT; -> SET c = 5; -> RETURN c; -> END $ Query OK, 0 rows affected (0.00 sec)mysql> delimiter ; 復制代碼

我們定義了一個名叫var_demo而且不需要參數的函數,我們在函數體中聲明了一個名稱為c的INT類型變量,之后我們調用SET語句為這個變量賦值了整數5,并且把變量c當作函數結果返回,我們調用一下這個函數:

mysql> select var_demo(); +------------+ | var_demo() | +------------+ | 5 | +------------+ 1 row in set (0.00 sec)mysql> 復制代碼

如果我們不對聲明的變量賦值的話,它的默認值就是NULL,當然我們也可以通過DEFAULT子句來顯式的指定變量的默認值,比如這樣:

mysql> delimiter $ mysql> CREATE FUNCTION var_default_demo() -> RETURNS INT -> BEGIN -> DECLARE c INT DEFAULT 1; -> RETURN c; -> END $ Query OK, 0 rows affected (0.00 sec)mysql> delimiter ; mysql> 復制代碼

在新創建的這個var_default_demo函數中,我們聲明了一個變量c,并且指定了它的默認值為1,然后看一下函數的調用結果:

mysql> SELECT var_default_demo(); +--------------------+ | var_default_demo() | +--------------------+ | 1 | +--------------------+ 1 row in set (0.00 sec)mysql> 復制代碼

得到的結果是1,說明了我們指定的變量默認值生效了!另外,特別需要注意一下我們可以將某個查詢語句的結果賦值給變量的情況,比如我們改寫一下前邊的avg_score函數:

CREATE FUNCTION avg_score(s VARCHAR(100)) RETURNS DOUBLE BEGINDECLARE a DOUBLE;SET a = (SELECT AVG(score) FROM student_score WHERE subject = s);return a; END 復制代碼

我們先把一個查詢語句的結果賦值給了變量a,然后再返回了這個變量。

參數的編寫

在定義函數的時候,可以指定多個參數,每個參數都要指定對應的數據類型,就像這樣:

參數名 數據類型 復制代碼

比如我們上邊編寫的這個avg_score函數:

CREATE FUNCTION avg_score(s VARCHAR(100)) RETURNS DOUBLE BEGINRETURN (SELECT AVG(score) FROM student_score WHERE subject = s); END 復制代碼

這個函數只需要一個類型為VARCHAR(100)參數,我們這里給這個參數起的名稱是s,需要注意的是,參數名不要和函數體語句中其他的變量名、命令語句的標識符沖突,比如如果把這個變量名命名為subject,它就與下邊用到WHERE子句中的列名沖突了,導致列名失效。

另外,函數參數不可以指定默認值,我們在調用函數的時候,必須顯式的指定所有的參數,并且參數類型也一定要匹配,比方說我們在調用函數avg_score時,必須指定我們要查詢的課程名,不然會報錯的:

mysql> select avg_score(); ERROR 1318 (42000): Incorrect number of arguments for FUNCTION xiaohaizi.avg_score; expected 1, got 0 mysql> 復制代碼
判斷語句的編寫

像其他的編程語言一樣,在MySQL的函數體里也可以使用判斷的語句,語法格式如下:

IF 布爾表達式 THEN 處理語句 [ELSEIF 布爾表達式 THEN處理語句] [ELSE 處理語句] END IF; 復制代碼

需要注意的是,這里的處理語句可以是由多條語句構成的復合語句。我們舉個例子:

mysql> delimiter $ mysql> CREATE FUNCTION condition_demo(i INT) -> RETURNS VARCHAR(10) -> BEGIN -> DECLARE result VARCHAR(10); -> IF i = 1 THEN -> SET result = '結果是1'; -> ELSEIF i = 2 THEN -> SET result = '結果是2'; -> ELSEIF i = 3 THEN -> SET result = '結果是3'; -> ELSE -> SET result = '非法參數'; -> END IF; -> RETURN result; -> END $ Query OK, 0 rows affected (0.00 sec)mysql> delimiter ; mysql> 復制代碼

在我們定義的函數condition_demo中,它接收一個INT類型的參數,這個函數的處理邏輯如下:

  • 如果這個參數的值是1,就把result變量的值設置為'結果是1'。
  • 否則如果這個這個參數的值是2,就把result變量的值設置為'結果是2'。
  • 否則如果這個這個參數的值是3,就把result變量的值設置為'結果是3'。
  • 否則就把result變量的值設置為'非法參數'。
  • 當然了,我們舉的這個例子還是比較白癡的啦,當然了,我們只是為了說明語法怎么用,等于到更復雜一點的業務邏輯再往復雜了說哈。我們現在調用一下這個函數:

    mysql> SELECT condition_demo(2); +-------------------+ | condition_demo(2) | +-------------------+ | 結果是2 | +-------------------+ 1 row in set (0.00 sec)mysql> SELECT condition_demo(5); +-------------------+ | condition_demo(5) | +-------------------+ | 非法參數 | +-------------------+ 1 row in set (0.00 sec)mysql> 復制代碼
    循環語句的編寫

    除了判斷語句,MySQL還支持循環語句的編寫,不過有3種形式的循環語句,我們一一道來:

    • WHILE循環語句:

      WHILE 布爾表達式 DO循環語句 END WHILE; 復制代碼

      這個語句的意思是:如果滿足給定的表達式,則執行循環語句,否則退出循環。比如我們想定義一個從1到n這n個數的和(假設n大于0),可以這么寫:

      mysql> delimiter $ mysql> CREATE FUNCTION sum_all(n INT UNSIGNED) -> RETURNS INT -> BEGIN -> DECLARE result INT DEFAULT 0; -> DECLARE i INT DEFAULT 1; -> WHILE i <= n DO -> SET result = result + i; -> SET i = i + 1; -> END WHILE; -> RETURN result; -> END $ Query OK, 0 rows affected (0.00 sec)mysql> delimiter ; mysql> 復制代碼

      在函數sum_all中,我們接收一個INT UNSIGNED類型的參數,聲明了兩個INT類型的變量i和result。我們先測試一下這個函數:

      mysql> SELECT sum_all(3); +------------+ | sum_all(3) | +------------+ | 6 | +------------+ 1 row in set (0.00 sec)mysql> 復制代碼

      分析一下這個結果是怎么產生的,初始的情況下result的值是0,i的值是1,給定的參數n的值是3。這個過程就是:

    • 先判斷i <= n是否成立,顯然成立,進入循環體,將result的值設置為1(result + i),i的值為2(i + 1)。
    • 再判斷i <= n是否成立,顯然成立,進入循環體,將result的值設置為3(result + i),i的值為3(i + 1)。
    • 再判斷i <= n是否成立,顯然成立,進入循環體,將result的值設置為6(result + i),i的值為4(i + 1)。
    • 再判斷i <= n是否成立,顯然不成立,退出循環。
    • 所以最后返回的result的值就是6,也就是1、2、3這三個數的和。

    • REPEAT循環語句

      REPEAT循環和WHILE循環差不多,只是形式上變了一下:

      REPEAT循環語句 UNTIL 布爾表達式 END REPEAT; 復制代碼

      先執行循環語句,再判斷布爾表達式是否成立,如果成立繼續執行循環語句,否則退出循環。與WHILE循環不同的一點是:WHILE循環先判斷布爾表達式的值,再執行循環語句,REPEAT循環先執行循環語句,再判斷布爾表達式的值,所以至少執行一次循環語句,所以如果sum_all函數用REPEAT循環改寫,可以寫成這樣:

      CREATE FUNCTION sum_all(n INT UNSIGNED) RETURNS INT BEGINDECLARE result INT DEFAULT 0;DECLARE i INT DEFAULT 1;REPEAT SET result = result + i;SET i = i + 1;UNTIL i <= n END REPEAT;RETURN result; END 復制代碼
    • LOOP循環語句

      這只是另一種形式的循環語句:

      循環標記:LOOP循環語句LEAVE 循環標記; END LOOP 循環標記; 復制代碼

      在LOOP循環語句中,比較特別的是需要我們設置循環標記來標識一個循環,在循環體內依靠 LEAVE 循環標記的形式來中斷某個循環,比方說我們可以把sum_all函數改寫成這樣:

      CREATE FUNCTION sum_all(n INT UNSIGNED) RETURNS INT BEGINDECLARE result INT DEFAULT 0;DECLARE i INT DEFAULT 1;flag:LOOP IF i > n THENLEAVE flag;END IF;SET result = result + i;SET i = i + 1;END LOOP flag;RETURN result; END 復制代碼

      其中的flag就是一個循環標記,在循環體內判斷i > n成立的時候就調用LEAVE flag來跳出這個循環。

    注釋的使用

    不論什么時候,對語句添加注釋都是一件好事兒!注釋不僅僅是幫助別人理解我們寫的語句是什么意思,對于我們自己來說,可能隔了幾天之后再看自己寫的語句就不知道是什么意思了。在函數體內以--開頭的語句都算作注釋語句,MySQL服務器在執行語句的時候會忽略掉這些注釋語句。

    -- 函數名:sum_all -- 參數:n = 從1累加到的數字CREATE FUNCTION sum_all(n INT UNSIGNED) COMMENT '求1到n這n個數的和' RETURNS INT BEGIN-- 當前累加的和DECLARE result INT DEFAULT 0;-- 當前累加的數字DECLARE i INT DEFAULT 1;-- 若當前累加的數字不大于指定數字,則繼續執行循環WHILE i <= n DOSET result = result + i;SET i = i + 1;END WHILE;-- 返回累加的和RETURN result; END 復制代碼

    除了--開頭的語句表示注釋,我們還可以在函數參數后寫COMMENT注釋語句說明這個函數的作用。

    小冊

    本系列專欄都是MySQL入門知識,想看進階知識可以到小冊中查看:《MySQL是怎樣運行的:從根兒上理解MySQL》的鏈接 。小冊的內容主要是從小白的角度出發,用比較通俗的語言講解關于MySQL進階的一些核心概念,比如記錄、索引、頁面、表空間、查詢優化、事務和鎖等,總共的字數大約是三四十萬字,配有上百幅原創插圖。主要是想降低普通程序員學習MySQL進階的難度,讓學習曲線更平滑一點~

    轉載于:https://juejin.im/post/5c9198f96fb9a070aa5ce939

    總結

    以上是生活随笔為你收集整理的MySQL入门系列:存储程序(二)之存储函数简介的全部內容,希望文章能夠幫你解決所遇到的問題。

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