MySQL存儲過程詳解

jopen 10年前發布 | 17K 次閱讀 MySQL 數據庫服務器

mysql存儲過程詳解

1.     存儲過程簡介

 

我們常用的操作數據庫語言SQL語句在執行的時候需要要先編譯,然后執行,而存儲過程(Stored Procedure)是一組為了完成特定功能的SQL語句集,經編譯后存儲在數據庫中,用戶通過指定存儲過程的名字并給定參數(如果該存儲過程帶有參數)來調用執行它。

一個存儲過程是一個可編程的函數,它在數據庫中創建并保存。它可以有SQL語句和一些特殊的控制結構組成。當希望在不同的應用程序或平臺上執行相同的函數,或者封裝特定功能時,存儲過程是非常有用的。數據庫中的存儲過程可以看做是對編程中面向對象方法的模擬。它允許控制數據的訪問方式。

存儲過程通常有以下優點:

(1).存儲過程增強了SQL語言的功能和靈活性。存儲過程可以用流控制語句編寫,有很強的靈活性,可以完成復雜的判斷和較復雜的運算。

(2).存儲過程允許標準組件是編程。存儲過程被創建后,可以在程序中被多次調用,而不必重新編寫該存儲過程的SQL語句。而且數據庫專業人員可以隨時對存儲過程進行修改,對應用程序源代碼毫無影響。

(3).存儲過程能實現較快的執行速度。如果某一操作包含大量的Transaction-SQL代碼或分別被多次執行,那么存儲過程要比批處理的執行速度快很多。因為存儲過程是預編譯的。在首次運行一個存儲過程時查詢,優化器對其進行分析優化,并且給出最終被存儲在系統表中的執行計劃。而批處理的Transaction-SQL語句在每次運行時都要進行編譯和優化,速度相對要慢一些。

(4).存儲過程能過減少網絡流量。針對同一個數據庫對象的操作(如查詢、修改),如果這一操作所涉及的Transaction-SQL語句被組織程存儲過程,那么當在客戶計算機上調用該存儲過程時,網絡中傳送的只是該調用語句,從而大大增加了網絡流量并降低了網絡負載。

(5).存儲過程可被作為一種安全機制來充分利用。系統管理員通過執行某一存儲過程的權限進行限制,能夠實現對相應的數據的訪問權限的限制,避免了非授權用戶對數據的訪問,保證了數據的安全。

 

2.     關于MySQL的存儲過程

存儲過程是數據庫存儲的一個重要的功能,但是MySQL5.0以前并不支持存儲過程,這使得MySQL在應用上大打折扣。好在MySQL 5.0終于開始已經支持存儲過程,這樣即可以大大提高數據庫的處理速度,同時也可以提高數據庫編程的靈活性。

3.     MySQL存儲過程的創建

 

(1).格式

MySQL存儲過程創建的格式:CREATE PROCEDURE 過程名 ([過程參數[,...]])
[
特性 ...]過程體

這里先舉個例子:
   

  1. mysql> DELIMITER //  
  2. mysql> CREATE PROCEDURE proc1(OUT int)  
  3.     -> BEGIN 
  4.     -> SELECT COUNT(*) INTO FROM user;  
  5.     -> END 
  6.     -> //  
  7. mysql> DELIMITER 
  8. </ol>

      
    注:

    1)這里需要注意的是DELIMITER //DELIMITER;兩句,DELIMITER是分割符的意思,因為MySQL默認以";"為分隔符,如果我們沒有聲明分割符,那么編譯器會把存儲過程當成SQL語句進行處理,則存儲過程的編譯過程會報錯,所以要事先用DELIMITER關鍵字申明當前段分隔符,這樣MySQL才會將";"當做存儲過程中的代碼,不會執行這些代碼,用完了之后要把分隔符還原。

    2)存儲過程根據需要可能會有輸入、輸出、輸入輸出參數,這里有一個輸出參數s,類型是int型,如果有多個參數用","分割開。

    3)過程體的開始與結束使用BEGINEND進行標識。

    這樣,我們的一個MySQL存儲過程就完成了,是不是很容易呢?看不懂也沒關系,接下來,我們詳細的講解。

     

    (2).聲明分割符

     

    其實,關于聲明分割符,上面的注解已經寫得很清楚,不需要多說,只是稍微要注意一點的是:如果是用MySQLAdministrator管理工具時,可以直接創建,不再需要聲明。

     

    (3).參數

    MySQL存儲過程的參數用在存儲過程的定義,共有三種參數類型,IN,OUT,INOUT,形式如:

    CREATE PROCEDURE([[IN |OUT |INOUT ]參數名數據類形...])

    IN輸入參數:表示該參數的值必須在調用存儲過程時指定,在存儲過程中修改該參數的值不能被返回,為默認值

    OUT輸出參數:該值可在存儲過程內部被改變,并可返回

    INOUT輸入輸出參數:調用時指定,并且可被改變和返回

    . IN參數例子

    創建:

    1. mysql DELIMITER //  
    2. mysql CREATE PROCEDURE demo_in_parameter(IN p_in int)  
    3. -> BEGIN   
    4. -> SELECT p_in;   
    5. -> SET p_in=2;   
    6. -> SELECT p_in;   
    7. -> END  
    8. -> //  
    9. mysql DELIMITER 
    10. </ol>


      執行結果
      :

      1. mysql SET @p_in=1;  
      2. mysql CALL demo_in_parameter(@p_in);  
      3. +------+  
      4. p_in |  
      5. +------+  
      6.      
      7. +------+  
      8.  
      9. +------+  
      10. p_in |  
      11. +------+  
      12.      
      13. +------+  
      14.  
      15. mysql> SELECT @p_in;  
      16. +-------+  
      17. @p_in |  
      18. +-------+  
      19.     |  
      20. +-------+  
      21. </ol>


        以上可以看出,
        p_in雖然在存儲過程中被修改,但并不影響@p_id的值

         

        .OUT參數例子

        創建:

        1. mysql DELIMITER //  
        2. mysql CREATE PROCEDURE demo_out_parameter(OUT p_out int)  
        3. -> BEGIN 
        4. -> SELECT p_out;  
        5. -> SET p_out=2;  
        6. -> SELECT p_out;  
        7. -> END;  
        8. -> //  
        9. mysql DELIMITER 
        10. </ol>


          執行結果
          :

          1. mysql SET @p_out=1;  
          2. mysql CALL sp_demo_out_parameter(@p_out);  
          3. +-------+  
          4. p_out   
          5. +-------+  
          6. NULL    
          7. +-------+  
          8.  
          9. +-------+  
          10. p_out |  
          11. +-------+  
          12.       
          13. +-------+  
          14.  
          15. mysql> SELECT @p_out;  
          16. +-------+  
          17. p_out |  
          18. +-------+  
          19.     |  
          20. +-------+  
          21. </ol>


            . INOUT參數例子

            創建:

            1. mysql DELIMITER //   
            2. mysql CREATE PROCEDURE demo_inout_parameter(INOUT p_inout int)   
            3. -> BEGIN 
            4. -> SELECT p_inout;  
            5. -> SET p_inout=2;  
            6. -> SELECT p_inout;   
            7. -> END;  
            8. -> //   
            9. mysql DELIMITER 
            10. </ol>

               

               

              執行結果:
              1. mysql > SET @p_inout=1;  
              2. mysql > CALL demo_inout_parameter(@p_inout) ;  
              3. +---------+  
              4. p_inout |  
              5. +---------+  
              6.       |  
              7. +---------+  
              8.  
              9. +---------+  
              10. p_inout   
              11. +---------+  
              12.       |  
              13. +---------+  
              14.  
              15. mysql > SELECT @p_inout;  
              16. +----------+  
              17. @p_inout   
              18. +----------+  
              19.        |  
              20. +----------+ 

              (4).變量

              .變量定義

              DECLARE variable_name [,variable_name...] datatype [DEFAULT value];

              其中,datatypeMySQL的數據類型,如:int, float, date, varchar(length)

              例如:

              1. DECLARE l_int int unsigned default 4000000;  
              2. DECLARE l_numeric number(8,2) DEFAULT 9.95;  
              3. DECLARE l_date date DEFAULT '1999-12-31';  
              4. DECLARE l_datetime datetime DEFAULT '1999-12-31 23:59:59';  
              5. DECLARE l_varchar varchar(255) DEFAULT 'This will not be padded'  

               

               

              .變量賦值

               SET變量名=表達式值[,variable_name = expression ...]

               

              .用戶變量

               

              .MySQL客戶端使用用戶變量

              1. mysql SELECT 'Hello World' into @x;  
              2. mysql SELECT @x;  
              3. +-------------+  
              4.   @x        |  
              5. +-------------+  
              6. Hello World |  
              7. +-------------+  
              8. mysql SET @y='Goodbye Cruel World';  
              9. mysql SELECT @y;  
              10. +---------------------+  
              11.     @y              |  
              12. +---------------------+  
              13. Goodbye Cruel World |  
              14. +---------------------+  
              15.  
              16. mysql SET @z=1+2+3;  
              17. mysql SELECT @z;  
              18. +------+  
              19. @z   |  
              20. +------+  
              21.    |  
              22. +------+  

              ⅱ.在存儲過程中使用用戶變量

              1. mysql CREATE PROCEDURE GreetWorld( SELECT CONCAT(@greeting,World');  
              2. mysql SET @greeting='Hello';  
              3. mysql CALL GreetWorld( );  
              4. +----------------------------+  
              5. CONCAT(@greeting,World'|  
              6. +----------------------------+  
              7.  Hello World               |  
              8. +----------------------------+  

               

              .在存儲過程間傳遞全局范圍的用戶變量
              1. mysql> CREATE PROCEDURE p1()   SET @last_procedure='p1';  
              2. mysql> CREATE PROCEDURE p2() SELECT CONCAT('Last procedure was ',@last_proc);  
              3. mysql> CALL p1( );  
              4. mysql> CALL p2( );  
              5. +-----------------------------------------------+  
              6. CONCAT('Last procedure was ',@last_proc  |  
              7. +-----------------------------------------------+  
              8. Last procedure was p1                         |  
              9. +-----------------------------------------------+  

               

               

              注意:

              用戶變量名一般以@開頭

              濫用用戶變量會導致程序難以理解及管理

               

              (5).注釋

               

              MySQL存儲過程可使用兩種風格的注釋

              雙模杠:--

              該風格一般用于單行注釋

              c風格:一般用于多行注釋

              例如:

               

              1. mysql DELIMITER //  
              2. mysql CREATE PROCEDURE proc1 --name存儲過程名 
              3. -> (IN parameter1 INTEGER  
              4. -> BEGIN   
              5. -> DECLARE variable1 CHAR(10);   
              6. -> IF parameter1 17 THEN   
              7. -> SET variable1 'birds'  
              8. -> ELSE 
              9. -> SET variable1 'beasts'  
              10. -> END IF;   
              11. -> INSERT INTO table1 VALUES (variable1);  
              12. -> END   
              13. -> //  
              14. mysql DELIMITER ;  

               

              4.     MySQL存儲過程的調用

              call和你過程名以及一個括號,括號里面根據需要,加入參數,參數包括輸入參數、輸出參數、輸入輸出參數。具體的調用方法可以參看上面的例子。

              5.     MySQL存儲過程的查詢

              我們像知道一個數據庫下面有那些表,我們一般采用show tables;行查看。那么我們要查看某個數據庫下面的存儲過程,是否也可以采用呢?答案是,我們可以查看某個數據庫下面的存儲過程,但是是令一鐘方式。

              我們可以用

              select name from mysql.proc where db=’數據庫名’;

              或者

              select routine_name from information_schema.routines where routine_schema='數據庫名';

              或者

              show procedure status where db='數據庫名';

              進行查詢。

              如果我們想知道,某個存儲過程的詳細,那我們又該怎么做呢?是不是也可以像操作表一樣用describe表名進行查看呢?

              答案是:我們可以查看存儲過程的詳細,但是需要用另一種方法:

              SHOW CREATE PROCEDURE數據庫.存儲過程名;

              就可以查看當前存儲過程的詳細。

               

              6.     MySQL存儲過程的修改

              ALTER PROCEDURE

              更改用CREATE PROCEDURE建立的預先指定的存儲過程,其不會影響相關存儲過程或存儲功能。

               

              7.     MySQL存儲過程的刪除

              刪除一個存儲過程比較簡單,和刪除表一樣:

              DROP PROCEDURE

              MySQL的表格中刪除一個或多個存儲過程。

               

              8.     MySQL存儲過程的控制語句

              (1).變量作用域

              內部的變量在其作用域范圍內享有更高的優先權,當執行到end。變量時,內部變量消失,此時已經在其作用域外,變量不再可見了,應為在存儲
              過程外再也不能找到這個申明的變量,但是你可以通過out參數或者將其值指派
              給會話變量來保存其值。

               

               

              1. mysql DELIMITER //  
              2. mysql CREATE PROCEDURE proc3()  
              3.      -> begin 
              4.      -> declare x1 varchar(5) default 'outer';  
              5.      -> begin 
              6.      -> declare x1 varchar(5) default 'inner';  
              7.      -> select x1;  
              8.      -> end;  
              9.      -> select x1;  
              10.      -> end;  
              11.      -> //  
              12. mysql DELIMITER ;  

               

               (2).條件語句

              . if-then -else語句

               

               

               

              1. mysql DELIMITER //  
              2. mysql CREATE PROCEDURE proc2(IN parameter int)  
              3.      -> begin 
              4.      -> declare var int;  
              5.      -> set var=parameter+1;  
              6.      -> if var=0 then 
              7.      -> insert into values(17);  
              8.      -> end if;  
              9.      -> if parameter=0 then 
              10.      -> update set s1=s1+1;  
              11.      -> else 
              12.      -> update set s1=s1+2;  
              13.      -> end if;  
              14.      -> end;  
              15.      -> //  
              16. mysql DELIMITER ;  


              . case語句:

              1. mysql DELIMITER //  
              2. mysql CREATE PROCEDURE proc3 (in parameter int)  
              3.      -> begin 
              4.      -> declare var int;  
              5.      -> set var=parameter+1;  
              6.      -> case var  
              7.      -> when then   
              8.      -> insert into values(17);  
              9.      -> when then   
              10.      -> insert into values(18);  
              11.      -> else   
              12.      -> insert into values(19);  
              13.      -> end case;  
              14.      -> end;  
              15.      -> //  
              16. mysql DELIMITER 

               

              (3).循環語句

              . while ···· end while

              1. mysql DELIMITER //  
              2. mysql CREATE PROCEDURE proc4()  
              3.      -> begin 
              4.      -> declare var int;  
              5.      -> set var=0;  
              6.      -> while var<6 do  
              7.      -> insert into values(var);  
              8.      -> set var=var+1;  
              9.      -> end while;  
              10.      -> end;  
              11.      -> //  
              12. mysql DELIMITER 

               

               

              . repeat···· end repeat

              它在執行操作后檢查結果,而while則是執行前進行檢查。

              1. mysql DELIMITER //  
              2. mysql CREATE PROCEDURE proc5 ()  
              3.      -> begin   
              4.      -> declare int;  
              5.      -> set v=0;  
              6.      -> repeat  
              7.      -> insert into values(v);  
              8.      -> set v=v+1;  
              9.      -> until v>=5  
              10.      -> end repeat;  
              11.      -> end;  
              12.      -> //  
              13. mysql DELIMITER ;  

               


              . loop ·····end loop:

              loop循環不需要初始條件,這點和while循環相似,同時和repeat循環一樣不需要結束條件, leave語句的意義是離開循環。

              1. mysql DELIMITER //  
              2. mysql CREATE PROCEDURE proc6 ()  
              3.      -> begin 
              4.      -> declare int;  
              5.      -> set v=0;  
              6.      -> LOOP_LABLE:loop  
              7.      -> insert into values(v);  
              8.      -> set v=v+1;  
              9.      -> if >=5 then 
              10.      -> leave LOOP_LABLE;  
              11.      -> end if;  
              12.      -> end loop;  
              13.      -> end;  
              14.      -> //  
              15. mysql DELIMITER ;  

               

               

              . LABLES標號:

              標號可以用在begin repeat while或者loop語句前,語句標號只能在合法的語句前面使用。可以跳出循環,使運行指令達到復合語句的最后一步。

               

              (4). ITERATE迭代

              . ITERATE:

              通過引用復合語句的標號,來從新開始復合語句

              1. mysql DELIMITER //  
              2. mysql CREATE PROCEDURE proc10 ()  
              3.      -> begin 
              4.      -> declare int;  
              5.      -> set v=0;  
              6.      -> LOOP_LABLE:loop  
              7.      -> if v=3 then   
              8.      -> set v=v+1;  
              9.      -> ITERATE LOOP_LABLE;  
              10.      -> end if;  
              11.      -> insert into values(v);  
              12.      -> set v=v+1;  
              13.      -> if v>=5 then 
              14.      -> leave LOOP_LABLE;  
              15.      -> end if;  
              16.      -> end loop;  
              17.      -> end;  
              18.      -> //  
              19. mysql DELIMITER 

               

               

              9.     MySQL存儲過程的基本函數

               

              (1).字符串類

              CHARSET(str) //返回字串字符集
              CONCAT (string2 [,... ]) //
              連接字串
              INSTR (string ,substring ) //
              返回substring首次在string中出現的位置,不存在返回0
              LCASE (string2 ) //
              轉換成小寫

              LEFT (string2 ,length ) //
              string2中的左邊起取length個字符
              LENGTH (string ) //string
              長度
              LOAD_FILE (file_name ) //
              從文件讀取內容
              LOCATE (substring , string [,start_position ] )
              INSTR,但可指定開始位置
              LPAD (string2 ,length ,pad ) //
              重復用pad加在string開頭,直到字串長度為length
              LTRIM (string2 ) //
              去除前端空格

              REPEAT (string2 ,count ) //
              重復count
              REPLACE (str ,search_str ,replace_str ) //
              str中用replace_str替換search_str
              RPAD (string2 ,length ,pad) //
              str后用pad補充,直到長度為
              length
              RTRIM (string2 ) //
              去除后端空格

              STRCMP (string1 ,string2 ) //
              逐字符比較兩字串大小,
              SUBSTRING (str , position [,length ]) //
              strposition開始,length個字符
              ,
              注:mysql中處理字符串時,默認第一個字符下標為1,即參數position必須大于等于1
               

               

              1. mysql> select substring('abcd',0,2);  
              2. +-----------------------+  
              3. substring('abcd',0,2) |  
              4. +-----------------------+  
              5.                       |  
              6. +-----------------------+  
              7. row in set (0.00 sec)  
              8.  
              9. mysql> select substring('abcd',1,2);  
              10. +-----------------------+  
              11. substring('abcd',1,2) |  
              12. +-----------------------+  
              13.     ab                |  
              14. +-----------------------+  
              15. row in set (0.02 sec)  

              TRIM([[BOTH|LEADING|TRAILING] [padding] FROM]string2) //去除指定位置的指定字符
              UCASE (string2 ) //
              轉換成大寫
              RIGHT(string2,length) //
              string2最后length個字符
              SPACE(count) //
              生成count個空格

              (2).數學類

              ABS (number2 ) //絕對值
              BIN (decimal_number ) //
              十進制轉二進制
              CEILING (number2 ) //
              向上取整
              CONV(number2,from_base,to_base) //
              進制轉換
              FLOOR (number2 ) //
              向下取整
              FORMAT (number,decimal_places ) //
              保留小數位數
              HEX (DecimalNumber ) //
              轉十六進制
              注:HEX()中可傳入字符串,則返回其ASC-11,如HEX('DEF')返回4142143
              也可以傳入十進制整數,返回其十六進制編碼,如HEX(25)返回
              19
              LEAST (number , number2 [,..]) //
              求最小值

              MOD (numerator ,denominator ) //
              求余
              POWER (number ,power ) //
              求指數
              RAND([seed]) //
              隨機數
              ROUND (number [,decimals ]) //
              四舍五入,decimals為小數位數]

              注:返回類型并非均為整數,如:
              (1)
              默認變為整形值

              1. mysql> select round(1.23);  
              2. +-------------+  
              3. round(1.23) |  
              4. +-------------+  
              5.           |  
              6. +-------------+  
              7. row in set (0.00 sec)  
              8.  
              9. mysql> select round(1.56);  
              10. +-------------+  
              11. round(1.56) |  
              12. +-------------+  
              13.           |  
              14. +-------------+  
              15. row in set (0.00 sec) 



              (2)
              可以設定小數位數,返回浮點型數據

              1. mysql> select round(1.567,2);  
              2. +----------------+  
              3. round(1.567,2) |  
              4. +----------------+  
              5.           1.57 |  
              6. +----------------+  
              7. row in set (0.00 sec) 

              SIGN (number2 ) //

               

              (3).日期時間類

              ADDTIME (date2 ,time_interval ) //time_interval加到date2
              CONVERT_TZ (datetime2 ,fromTZ ,toTZ ) //
              轉換時區
              CURRENT_DATE ( ) //
              當前日期
              CURRENT_TIME ( ) //
              當前時間
              CURRENT_TIMESTAMP ( ) //
              當前時間戳
              DATE (datetime ) //
              返回datetime的日期部分
              DATE_ADD (date2 , INTERVAL d_value d_type ) //
              date2中加上日期或時間
              DATE_FORMAT (datetime ,FormatCodes ) //
              使用formatcodes格式顯示datetime
              DATE_SUB (date2 , INTERVAL d_value d_type ) //
              date2上減去一個時間
              DATEDIFF (date1 ,date2 ) //
              兩個日期差
              DAY (date ) //
              返回日期的天
              DAYNAME (date ) //
              英文星期
              DAYOFWEEK (date ) //
              星期(1-7) ,1為星期天
              DAYOFYEAR (date ) //
              一年中的第幾天
              EXTRACT (interval_name FROM date ) //
              date中提取日期的指定部分
              MAKEDATE (year ,day ) //
              給出年及年中的第幾天,生成日期串
              MAKETIME (hour ,minute ,second ) //
              生成時間串
              MONTHNAME (date ) //
              英文月份名
              NOW ( ) //
              當前時間
              SEC_TO_TIME (seconds ) //
              秒數轉成時間
              STR_TO_DATE (string ,format ) //
              字串轉成時間,format格式顯示
              TIMEDIFF (datetime1 ,datetime2 ) //
              兩個時間差
              TIME_TO_SEC (time ) //
              時間轉秒數]
              WEEK (date_time [,start_of_week ]) //
              第幾周
              YEAR (datetime ) //
              年份
              DAYOFMONTH(datetime) //
              月的第幾天
              HOUR(datetime) //
              小時
              LAST_DAY(date) //date
              的月的最后日期
              MICROSECOND(datetime) //
              微秒
              MONTH(datetime) //

              MINUTE(datetime) //
              返回符號,正負或0
              SQRT(number2) //
              開平方
               
               
 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!