MySQL-5.7 存儲過程及函數


1.語法

CREATE
    [DEFINER = { user | CURRENT_USER }]
    PROCEDURE sp_name ([proc_parameter[,...]])
    [characteristic ...] routine_body

CREATE
    [DEFINER = { user | CURRENT_USER }]
    FUNCTION sp_name ([func_parameter[,...]])
    RETURNS type
    [characteristic ...] routine_body

proc_parameter:
    [ IN | OUT | INOUT ] param_name type

func_parameter:
    param_name type

type:
    Any valid MySQL data type

characteristic:
    COMMENT 'string'
  | LANGUAGE SQL
  | [NOT] DETERMINISTIC
  | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
  | SQL SECURITY { DEFINER | INVOKER }

routine_body:
    Valid SQL routine statement

參數詳解:
(1)DEFINER
表示創建存儲過程及函數的用戶,默認為當前用戶;
(2)func_parameter
表示存儲過程的參數。在Create Procedure 語句中,可以聲明一個或多個參數。當調用該存儲過程時,用戶必須給出所有的參數值,除非定義了參數的缺省值。若參數的形式以 @parameter=value 出現,則參數的次序可以不同,否則用戶給出的參數值必須與參數列表中參數的順序保持一致。若某一參數以@parameter=value 形式給出,那么其它參數也必須以該形式給出。一個存儲過程至多有1024 個參數。
(3)characteristic

  • LANGUAGE SQL:表示此存儲過程和函數的創建語言;
  • [NOT] DETERMINISTIC:表明輸入相同的參數會返回相同的結果,反之表示相同的參數不會是相同的結果,默認是not deterministic;
  • -- CONTAINS SQL :子程序不包含讀或寫數據的語句;
  • -- NO SQL : 子程序不包含SQL語句;
  • -- READS SQL DATA :子程序包含讀數據的語句;
  • -- MODIFIES SQL DATA : 子程序包含寫數據的語句;
  • -- 如果這些特征沒有明確給定,默認的是CONTAINS SQL;

(4)SQL SECURITY { DEFINER | INVOKER }
子程序該用創建子程序者的許可來執行,還是使用調用者的許可來執行。默認值是DEFINER。
(5)COMMENT
是一個MySQL的擴展,它可以被用來描述存儲程序。這個信息被SHOW CREATE PROCEDURE和 SHOW CREATE FUNCTION語句來顯示。

2.存儲過程與函數特性

(1)存儲過程與函數的區別

  • 函數調用有返回值
  • 存儲過程調用用call語句,函數調用直接飲用函數名+參數

(2)Definer和sql security

  • Definder是MySQL的特殊訪問控制手段,當數據庫當前沒有這個用戶權限時,執行存儲過程可能會報錯;
  • sql security的值決定了調用存儲過程的方式,取值:definer(默認)或invoker;
  • definer在執行時先驗證definer對應的用戶,如:cdq@127.0.0.1是否存在,以及是否具有執行存儲過程的權限,若沒有則報錯;
  • invoker在執行存儲過程時判斷invoker,即調用該存儲過程的用戶是否有相應權限,若沒有則報錯

(3)IN,OUT,INOUT
只適用於存儲過程,對函數而言所有參數默認都是輸入參數

  • IN用於把數值傳入到存儲過程中
  • OUT用於輸出參數將數值傳遞給調用者
  • INOUT輸入輸出參數把數據傳入到存儲過程,在存儲過程中修改后再傳遞給調用者

3.實例演示

(1)簡單存儲過程

mysql> delimiter //
mysql> create procedure simpleproc(in param1 int,out param2 int)
    -> begin
    -> select count(*) into param2 from students where sid > param1;
    -> end//
Query OK, 0 rows affected (0.02 sec)

mysql> delimiter ;
mysql> call simpleproc(1,@a);
Query OK, 1 row affected (0.00 sec)

mysql> select @a;
+------+
| @a   |
+------+
|    7 |
+------+
1 row in set (0.00 sec)

說明:

  • delimiter命令是改變語句的結束符,MySQL默認結束符為;號,由於存儲過程和函數中的;號並不代表結束,所以要替換另外的結束符;

(2)簡單的函數

mysql> create function hello(s char(20))
    -> returns char(50)
    -> return concat('Hello',s,'!');
Query OK, 0 rows affected (0.00 sec)

mysql> select hello('world');
+----------------+
| hello('world') |
+----------------+
| Helloworld!    |
+----------------+
1 row in set (0.00 sec)

(3)復雜的示例

mysql> delimiter //
mysql> create function simplefunc(param1 int)
    -> returns int
    -> begin
    -> update students set gender=1 where sid=param1;
    -> select count(*) into @a from students where sid > param1;
    -> return @a;
    -> end//
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
mysql> select * from students where sid=1;
+-----+--------+--------+---------+
| sid | sname  | gender | dept_id |
+-----+--------+--------+---------+
|   1 | Andrew | 0      |       1 |
+-----+--------+--------+---------+
1 row in set (0.00 sec)

mysql> select simplefunc(1);
+---------------+
| simplefunc(1) |
+---------------+
|             7 |
+---------------+
1 row in set (0.03 sec)

mysql> select * from students where sid=1;
+-----+--------+--------+---------+
| sid | sname  | gender | dept_id |
+-----+--------+--------+---------+
|   1 | Andrew | 1      |       1 |
+-----+--------+--------+---------+
1 row in set (0.01 sec)

說明:

  • MySQL存儲過程和函數中也可以包含類似create和drop等DDL語句;
  • rontine_body子句可以包含一個簡單的SQL語句,也可以包含多個SQL語句,通過begin...end將多個SQL語句包含在一起;

4.測試definer

[root@localhost ~]# mysql -uabc2 -p
Enter password: 

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| course             |
+--------------------+
2 rows in set (0.01 sec)

mysql> use course;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> delimiter //
mysql> create procedure simpleproc2(IN param1 int,out param2 int)
    -> begin
    -> select count(*) into param2 from students where sid > param1;
    -> end//
Query OK, 0 rows affected (0.00 sec)

[root@localhost ~]# mysql -p
Enter password: 

mysql> use course;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> call simpleproc2(1,@a);
Query OK, 1 row affected (0.00 sec)

mysql> drop user 'abc2'@'localhost';
Query OK, 0 rows affected (0.00 sec)

mysql> call simpleproc2(1,@a);
ERROR 1449 (HY000): The user specified as a definer ('abc2'@'localhost') does not exist

查看存儲過程及函數的相關數據庫信息(在information_schema庫)
mysql> select ROUTINE_SCHEMA,ROUTINE_NAME,ROUTINE_TYPE,ROUTINE_BODY,ROUTINE_DEFINITION,DEFINER from ROUTINES where ROUTINE_SCHEMA = 'course';
+----------------+--------------+--------------+--------------+-------------------------------------------------------------------------------------------------------------------------------+----------------+
| ROUTINE_SCHEMA | ROUTINE_NAME | ROUTINE_TYPE | ROUTINE_BODY | ROUTINE_DEFINITION                                                                                                            | DEFINER        |
+----------------+--------------+--------------+--------------+-------------------------------------------------------------------------------------------------------------------------------+----------------+
| course         | hello        | FUNCTION     | SQL          | return concat('Hello',s,'!')                                                                                                  | root@localhost |
| course         | simplefunc   | FUNCTION     | SQL          | begin
update students set gender=1 where sid=param1;
select count(*) into @a from students where sid > param1;
return @a;
end | root@localhost |
| course         | simpleproc   | PROCEDURE    | SQL          | begin
select count(*) into param2 from students where sid > param1;
end                                                       | root@localhost |
| course         | simpleproc2  | PROCEDURE    | SQL          | begin
select count(*) into param2 from students where sid > param1;
end                                                       | abc2@localhost |
+----------------+--------------+--------------+--------------+-------------------------------------------------------------------------------------------------------------------------------+----------------+

mysql> alter procedure simpleproc2 sql security invoker;
Query OK, 0 rows affected (0.00 sec)

mysql> call simpleproc2(1,@a);
Query OK, 1 row affected (0.00 sec)

說明:
相關屬性短語只有咨詢含義,並不是強制性約束

  • contains sql表明此存儲過程或函數不包含讀或者寫數據的語句,這是默認屬性;
  • no sql表明此存儲過程或函數不包含SQL語句
  • reads sql data表示此存儲過程包含諸如select的查詢數據的語句,但不包含插入或刪除數據的語句
  • modifies sql data表示存儲過程包含插入或刪除數據的語句

5.刪除語句

DROP {procedure | function} {IF EXISTS} sp_name;

if exists用來避免在刪除一個本身不存在的存儲過程或函數時,MySQL返回錯誤;

mysql> drop procedure oldboy;
ERROR 1305 (42000): PROCEDURE course.oldboy does not exist
mysql> drop procedure if exists oldboy;
Query OK, 0 rows affected, 1 warning (0.00 sec)

6.查看存儲過程及函數

mysql> show create procedure simpleproc;
+------------+-------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+
| Procedure  | sql_mode                                                                                                                                  | Create Procedure                                                                                                                                               | character_set_client | collation_connection | Database Collation |
+------------+-------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+
| simpleproc | 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_SUBSTITUTION | CREATE DEFINER=`root`@`localhost` PROCEDURE `simpleproc`(in param1 int,out param2 int)
begin
select count(*) into param2 from students where sid > param1;
end | utf8                 | utf8_general_ci      | latin1_swedish_ci  |
+------------+-------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+
mysql> show create function simplefunc;
+------------+-------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+
| Function   | sql_mode                                                                                                                                  | Create Function                                                                                                                                                                                                   | character_set_client | collation_connection | Database Collation |
+------------+-------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+
| simplefunc | 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_SUBSTITUTION | CREATE DEFINER=`root`@`localhost` FUNCTION `simplefunc`(param1 int) RETURNS int(11)
begin
update students set gender=1 where sid=param1;
select count(*) into @a from students where sid > param1;
return @a;
end | utf8                 | utf8_general_ci      | latin1_swedish_ci  |
+------------+-------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+
1 row in set (0.01 sec)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM