1. 程式人生 > >mysql的高階特性-儲存過程

mysql的高階特性-儲存過程

定義: 

  儲存例程是儲存在資料庫伺服器中的一組sql語句,通過在查詢中呼叫一個指定的名稱來執行這些sql語句命令.

語法:

DELIMITER // 宣告語句結束符,用於區分; 
    CEATE PROCEDURE demo_in_parameter(IN p_huhy int) 宣告儲存過程 
    BEGIN
        sql語句體;
    END 儲存過程開始和結束符號 
    SET @p_huhy=1 變數賦值 
    DECLARE huhy_int int unsigned default 400; 變數定義

  注意:varchar型別資料必須加限定  varcahr(
12)

  儲存過程(stored procedure)、儲存例程(store routine)、儲存函式區別 
  Mysql儲存例程實際包含了儲存過程和儲存函式,它們被統稱為儲存例程。 
  其中儲存過程主要完成在獲取記錄或插入記錄或更新記錄或刪除記錄,即完成select insert delete update等的工作。而儲存函式只完成查詢的工作,可接受輸入引數並返回一個結果。

  例項介紹:
    mysql> DELIMITER ;; 
    mysql> CREATE PROCEDURE huhy_count(OUT s int) 
    -> BEGIN
    -> SELECT COUNT(*) INTO s FROM user; 
    -> END
    -> ;; 
    mysql> DELIMITER ;

注: 
(1)這裡需要注意的是DELIMITER//和DELIMITER;兩句,DELIMITER是分割符的意思,因為MySQL預設以”;”為分隔 符,如果我們沒有宣告分割符,那麼編譯器會把儲存過程當成SQL語句進行處理,則儲存過程的編譯過程會報錯,所以要事先用DELIMITER關鍵字申明當 前段分隔符,這樣MySQL才會將”;”當做儲存過程中的程式碼,不會執行這些程式碼,用完了之後要把分隔符還原。 
(2)儲存過程根據需要可能會有輸入、輸出、輸入輸出引數,這裡有一個輸出引數s,型別是int型,如果有多個引數用”,”分割開。 
(3)過程體的開始與結束使用BEGIN與END進行標識。

儲存過程的引數:

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

    CREATE PROCEDURE 儲存過程名([[IN |OUT |INOUT ] 引數名 資料類形…])

  IN 輸入引數:表示該引數的值必須在呼叫儲存過程時指定,在儲存過程中修改該引數的值不能被返回,為預設值
  OUT 輸出引數:該值可在儲存過程內部被改變,並可返回
  INOUT 輸入輸出引數:呼叫時指定,並且可被改變和返回

  note:關於引數的使用我會在建立儲存過程的時候再詳細介紹

區域性變數

  定義:區域性變數宣告一定要放在儲存過程體的開始 

    DECLAREvariable_name [,variable_name…] datatype [DEFAULT value];
    其中,datatype為MySQL的資料型別,如:int, float, date,varchar(length)
    eg:
      DECLARE huhy_int int unsigned default 12;
      DECLARE huhy_numeric number(5,2) DEFAULT 9.01;
      DECLARE huhy_date date DEFAULT '2007-12-31';
      DECLARE huhy_datetime datetime DEFAULT '2008-12-31 23:59:59';
      DECLARE huhy_varchar varchar(255) DEFAULT 'is huhy';

  變數賦值:
    SET 變數名 = 表示式值 [,variable_name = expression …]

使用者變數:

note:
  使用者變數名一般以@開頭
  濫用使用者變數會導致程式難以理解及管理

  1>在儲存過程間傳遞全域性範圍的使用者變數
    mysql> CREATE PROCEDURE yang_1() SET @huhy_procedure='good';
    mysql> CREATE PROCEDURE yang_2() SELECT CONCAT('huhy is ',@huhy_procedure);
    mysql> CALL yang_1( );
    mysql> CALL yang_2( );
      +-----------------------------------------------+
      | CONCAT('huhy is ',@huhy_procedure |
      +-----------------------------------------------+
      | huhy is good                                       |
      +-----------------------------------------------+
  2>在儲存過程中使用使用者變數
    mysql > CREATE PROCEDURE GreetWorld( ) SELECT CONCAT(@greeting,' World');
    mysql > SET @greeting='Hello';
    mysql > CALL GreetWorld( );
      +----------------------------+
      | CONCAT(@greeting,' World') |
      +----------------------------+
      | Hello World                  |
      +----------------------------+
  3>在MySQL客戶端使用使用者變數
    mysql > SELECT 'Hello World' into @x;
    mysql > SELECT @x;
      +-------------+
      | @x |
      +-------------+
      | Hello World |
      +-------------+ 

註釋:

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

  雙模槓:–- 該風格一般用於單行註釋
  c風格: 一般用於多行註釋 /********************* 建立表 *****************************/

 

MySQL儲存過程的呼叫

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

MySQL儲存過程的查詢

  我們像知道一個數據庫下面有那些表,我們一般採用showtables;進行檢視。那麼我們要檢視某個資料庫下面的儲存過程,是否也可以採用呢?答案是,我們可以檢視某個資料庫下面的儲存過程,但是是令一鍾方式。 我們可以用 selectname from mysql.proc where db=’資料庫名’; 或者 selectroutine_name from information_schema.routines where routine_schema=’資料庫名’; 或者 showprocedure status where db=’資料庫名’; 進行查詢。 如果我們想知道,某個儲存過程的詳細,那我們又該怎麼做呢?是不是也可以像操作表一樣用describe 表名進行檢視呢? 答案是:我們可以檢視儲存過程的詳細,但是需要用另一種方法: 

SHOWCREATE PROCEDURE 資料庫.儲存過程名;
就可以檢視當前儲存過程的詳細。

MySQL儲存過程的修改

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

 

MySQL儲存過程的刪除


  刪除一個儲存過程比較簡單,和刪除表一樣:
  DROP PROCEDURE
  從MySQL的表格中刪除一個或多個儲存過程。

 

MySQL儲存過程的基本函式

字串類        
        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 ]) //從str的position開始,取length個字元,
                注:mysql中處理字串時,預設第一個字元下標為1,即引數position必須大於等於1 
                1.  mysql> select substring('abcd',0,2);  
                2.  +-----------------------+  
                3.  | substring('abcd',0,2) |  
                4.  +-----------------------+  
                5.  |                       |  
                6.  +-----------------------+  
                7.  1 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.1 row in set (0.02 sec)  
        TRIM([[BOTH|LEADING|TRAILING][padding] FROM]string2) //去除指定位置的指定字元
        UCASE (string2 ) //轉換成大寫
        RIGHT(string2,length) //取string2最後length個字元
        SPACE(count) //生成count個空格
    數學類
        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.  |           1 |  
                6.  +-------------+  
                7.  1 row in set (0.00 sec)  
                8.   
                9.  mysql> select round(1.56);  
                10.+-------------+  
                11.| round(1.56) |  
                12.+-------------+  
                13.|           2 |  
                14.+-------------+  
                15.1 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.  1 row in set (0.00 sec) 
        SIGN (number2 ) //
    日期時間類
        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) //開平方

mybatis操作mysql儲存過程:

  假設操作環境已經搭建完成。下面就來對其進行測試:

  介面如下:

    

  xml配置如下:

    

  測試如下:

    


總結:

  以上就是mybatis對儲存過程的簡單操作:關於儲存過程如下:  

1> 查詢表資料總共多少
    CREATE DEFINER=`huhy`@`%` PROCEDURE `huhy_count`(OUT `sum` int)
    BEGIN
        select count(*) INTO sum from user;
    END

    note: varchar型別資料必須加限定 eg varcahr(11),
    
2> 表名作為儲存引數傳入儲存過程

DROP PROCEDURE IF EXISTS `pagePro`;
CREATE DEFINER = `root`@`localhost` PROCEDURE `pagePro`(in pageNo int,in pageSize int,in tableName varchar(50))
BEGIN
    DECLARE startIndex INT;
    set startIndex = pageSize * (pageNo-1);
    set @s = concat("select * from ",tableName," LIMIT ",startIndex,",",pageSize);
    prepare stmt from @s;
    execute stmt;
    DEALLOCATE prepare stmt;
END;

    mysql 是不支援表名,列名做引數的.只能採用動態拼接的方法來生成sql語句.

note:傳入三個引數,pageNo 是頁號,pageSize是一頁顯示的記錄數量,tableName是表名.
  eg:call pagePro(2,3,'student');

  大家要注意:儲存過程的一些特性,比如原生的儲存過程不允許傳表名,列名,等,還有儲存過程的語法,注意項。有興趣的可以去試一下。合理的利用儲存過程會極大的提高程式碼的效能。但並不是儲存過程越多越好,大家合理掌握瓶頸問題。