Linux学习-存储过程及函数

Posted 丢爸

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux学习-存储过程及函数相关的知识,希望对你有一定的参考价值。

存储过程与函数

mysql从5.0版本开始支持存储过程和函数,存储过程和函数能够将复杂的SQL封装在一起,应用程序无须关注存储过程和函数内部复杂的SQL逻辑,而只需简单的调用存储过程和函数即可
存储过程
存储过程(Stored Procedure),是一组经过预先编译的SQL语句的封装。
存储过程预先存储在MySQL服务器上,需要执行的时候,客户端向服务器发出调用存储过程命令,服务器端把预先存储好的一系列SQL语句全部执行
优点:
 - 简化操作,提高SQL语句的重用性,减少开发程序员的压力
 - 减少操作过程中的失误,提高效率
 - 减少网络传输量(客户端不需要把所有SQL语句通过网络发送给服务器)
 - 减少SQL语句暴露在网上的风险,也提高了数据查询的安全性
分类:
注:INOUT、INTOUT都可以在一个存储过程中带多个
 - 没有参数(无参数无返回)
 - 仅带IN参数(有参数无返回)
 - 仅带OUT参数(无参数有返回)
 - 既带IN又带OUT参数(有参数有返回)
 -INOUT(有参数有返回)
语法:
CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型)
[characteristics...]
BEGIN
存储过程体
END
注:
1. 参数前面符号意思
 - IN:当前参数为输入参数,表示入参,存储过程只读取这个参数值,如没定义参数种类,默认是IN,表示输入参数
 - OUT:当前参数为输出参数,表示出参,执行完成后,调用这个存储过程的客户端或应用程序可以读取这个参数返回值
 - INOUT:当前参数既可做输入参数,也可做输出参数
2.形参类型可以是MySQL数据库中任何类型
3.characteristics表示创建存储过程时指定的对存储过程的约束条件,其取值信息如下

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

- LANGUAGE SQL:说明存储过程执行体是由SQL语句组成的,当前系统支持的语言为SQL
- [NOT] DETERMINISTIC:指明存储过程执行的结果是否确定,DETERMINISTIC表示确定,每次执行存储过程时,相同的输入会得到相同输出,NOT DETERMINISTIC表示结果是不确定的,相同的输入可能得到不同输出,如没有指定任意一个值,默认为NOT DETERMINISTIC
- CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA 
+ CONTAINS SQL表示当前存储过程的子程序包含SQL语句,但并不包含读写数据的SQL
+ NO SQL表示当前存储过程的子程序中不包含任何SQL语句
+ READS SQL DATA表示当前存储过程的子程序中包含读数据的SQL语句
+ MODIFIES SQL DATA表示当前存储过程的子程序中包含写数据的SQL语句
- SQL SECURITY DEFINER|INVOKER执行存储过程的权限,即指明哪些用户能够执行当前存储过程
+ DEFINER表示只有当前存储过程的创建者或定义者才能执行当前存储过程
+ INVOKER表示拥有当前存储过程的访问权限的用户能够执行当前存储过程
4.存储过程可以有多条SQL语句,如仅一条SQL语句,则可以省略BEGINEND
5.需要设置新的结束标记 DELIMITER $

创建存储过程
1.无参存储过程
#切换结尾符
mysql> delimiter $
mysql> create procedure select_all_data()
    -> begin
    -> select * from employees;
    -> end $
Query OK, 0 rows affected (0.06 sec)
mysql> delimiter ;
mysql> show procedure status like 'select%';
+----------+-----------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
| Db       | Name            | Type      | Definer        | Modified            | Created             | Security_type | Comment | character_set_client | collation_connection | Database Collation |
+----------+-----------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
| dbtest15 | select_all_data | PROCEDURE | root@localhost | 2022-09-22 02:18:52 | 2022-09-22 02:18:52 | DEFINER       |         | utf8mb4              | utf8mb4_0900_ai_ci   | utf8mb4_0900_ai_ci |
+----------+-----------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
1 row in set (0.00 sec)
#调用存储过程
mysql> call select_all_data();
2.OUT存储过程
mysql> delimiter $
mysql> create procedure show_min_salary(OUT ms double)
    -> begin
    -> select min(salary) into ms from employees;
    -> end $
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
#通过@定义变量
mysql> call show_min_salary(@ms);
Query OK, 1 row affected (0.00 sec)
mysql> select @ms;
+------+
| @ms  |
+------+
| 2100 |
+------+
1 row in set (0.00 sec)
3.IN参数,创建存储过程show_someone_salary(),查看employees表某个员工的工资
mysql> delimiter $
mysql> create procedure show_someone_salary(IN empname varchar(20))
    -> begin
    -> select salary from employees where last_name=empname;
    -> end $
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
mysql> call show_someone_salary('Fay');
+---------+
| salary  |
+---------+
| 6000.00 |
+---------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)
3.INOUT
mysql> DELIMITER $
mysql> CREATE PROCEDURE show_someone_salary2(IN empname varchar(20),OUT empsalary double(10,2))
    -> BEGIN
    -> select salary into empsalary from employees where last_name=empname; 
    -> END $
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> DELIMITER ;
mysql> call show_someone_salary2('Fay',@empsalary);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT @empsalary;
+------------+
| @empsalary |
+------------+
|       6000 |
+------------+
1 row in set (0.00 sec)
4.INOUT,创建存储过程show_mgr_name(),查询某个员工领导的姓名
mysql> DELIMITER $
mysql> CREATE PROCEDURE show_mgr_name(INOUT empname VARCHAR(25))
    -> BEGIN
    -> SELECT last_name FROM employees WHERE employee_id=(SELECT manager_id  FROM employees WHERE last_name=empname);
    -> END $
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ;
mysql> set @empname='Fay';
Query OK, 0 rows affected (0.01 sec)

mysql> call show_mgr_name(@empname);
+-----------+
| last_name |
+-----------+
| Hartstein |
+-----------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)
存储函数
语法
CREATE FUNCTION 函数名(参数名 参数类型,...)
RETURNS 返回值类型
[characteristics]
BEGIN
函数体 #函数体中有RETURN语句
END
1.参数列表:指定参数为IN,OUTINOUT只对PROCEDURE是合法的,FUNCTION中总是默认为IN参数
2.RETURNS type语句表示函数返回数据的类型(RETURNS子句只能对FUNCTION做指定,对函数而言这是强制的,它用来指定函数的返回类型,而函数体必须包含一个RETURN value语句)
3.characteristic创建函数时指定对函数的约束,取值与创建存储过程相同。
4.BEGIN开始,END结束
事例
1.创建存储函数,名称为email_by_name(),返回Fay的邮箱
mysql> DELIMITER $
mysql> CREATE FUNCTION email_by_name()
    -> RETURNS VARCHAR(25)
    -> BEGIN
    -> RETURN (SELECT email from employees where last_name='Fay');
    -> END $
ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
#解决上述错误①
mysql> CREATE FUNCTION email_by_name()
    -> RETURNS VARCHAR(25)
    -> DETERMINISTIC
    -> CONTAINS SQL
    -> READS SQL DATA
    -> BEGIN
    -> RETURN (SELECT email from employees where last_name='Fay');
    -> END $
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT email_by_name();
    -> $
+-----------------+
| email_by_name() |
+-----------------+
| PFAY            |
+-----------------+
1 row in set (0.00 sec)
mysql> DELIMITER ;
#解决上述错误②
mysql> SET GLOBAL log_bin_trust_function_creators=1;
Query OK, 0 rows affected (0.00 sec)
2.创建存储函数,名称为email_by_id(),参数传入emp_id
mysql> DELIMITER $
mysql> CREATE FUNCTION email_by_id(emp_id int) RETURNS VARCHAR(25) BEGIN RETTURN (SELECT email FROM employees where employee_id=emp_id); END$
mysql> DELIMITER ;
mysql> select email_by_id(110);
+------------------+
| email_by_id(110) |
+------------------+
| JCHEN            |
+------------------+
1 row in set (0.01 sec)

对比存储函数和存储过程
<table>
<th><td></td><td>关键字</td><td>调用语法</td><td>返回值</td><td>应用场景</td></th>
<td><td>存储过程</td><td>PROCEDURE</td><td>CALL 存储过程()</td><td>0或者多个</td><td>一般用于更新</td></td>
<td><td>存储函数</td><td>FUNCTION</td><td>SELECT 函数名()</td><td>只能是一个</td><td>一般用于查询一个值并返回</td></td>
</table>
<h2>存储函数可以放在查询语句中使用,存储过程不行,反之,存储过程的功能更强大,包括能够执行对表的操作(创建表、删除表等)和事务操作,这些功能是存储函数不具备的</h2>
查看存储过程、存储函数
1.通过show create [procedure|function] 函数名或存储过程名称查看
#查看存储过程
mysql> SHOW CREATE PROCEDURE show_mgr_name\\G;
*************************** 1. row ***************************
           Procedure: show_mgr_name
            sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
    Create Procedure: CREATE DEFINER=`root`@`localhost` PROCEDURE `show_mgr_name`(INOUT empname VARCHAR(25))
BEGIN
SELECT last_name from employees WHERE employee_id=(SELECT manager_id  from employees WHERE last_name=empname);
END
character_set_client: utf8mb4
collation_connection: utf8mb4_0900_ai_ci
  Database Collation: utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

ERROR: 
No query specified

#查看存储函数 
mysql> SHOW CREATE FUNCTION email_by_id\\G;
*************************** 1. row ***************************
            Function: email_by_id
            sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
     Create Function: CREATE DEFINER=`root`@`localhost` FUNCTION `email_by_id`(emp_id int) RETURNS varchar(25) CHARSET utf8mb4
BEGIN RETURN (SELECT email FROM employees where employee_id=emp_id); END
character_set_client: utf8mb4
collation_connection: utf8mb4_0900_ai_ci
  Database Collation: utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

ERROR: 
No query specified
2.通过 SHOW STATUS 查看存储过程和函数的状态信息
mysql> SHOW PROCEDURE STATUS LIKE 'show_mgr_name'\\G;
*************************** 1. row ***************************
                  Db: dbtest15
                Name: show_mgr_name
                Type: PROCEDURE
             Definer: root@localhost
            Modified: 2022-09-22 02:54:54
             Created: 2022-09-22 02:54:54
       Security_type: DEFINER
             Comment: 
character_set_client: utf8mb4
collation_connection: utf8mb4_0900_ai_ci
  Database Collation: utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

ERROR: 
No query specified
3.通过information_schema.Routines表中查看
mysql> select * from information_schema.Routines where ROUTINE_NAME='email_by_id' and ROUTINE_TYPE='FUNCTION'\\G;
*************************** 1. row ***************************
           SPECIFIC_NAME: email_by_id
         ROUTINE_CATALOG: def
          ROUTINE_SCHEMA: dbtest15
            ROUTINE_NAME: email_by_id
            ROUTINE_TYPE: FUNCTION
               DATA_TYPE: varchar
CHARACTER_MAXIMUM_LENGTH: 25
  CHARACTER_OCTET_LENGTH: 100
       NUMERIC_PRECISION: NULL
           NUMERIC_SCALE: NULL
      DATETIME_PRECISION: NULL
      CHARACTER_SET_NAME: utf8mb4
          COLLATION_NAME: utf8mb4_0900_ai_ci
          DTD_IDENTIFIER: varchar(25)
            ROUTINE_BODY: SQL
      ROUTINE_DEFINITION: BEGIN RETURN (SELECT email FROM employees where employee_id=emp_id); END
           EXTERNAL_NAME: NULL
       EXTERNAL_LANGUAGE: SQL
         PARAMETER_STYLE: SQL
        IS_DETERMINISTIC: NO
         SQL_DATA_ACCESS: CONTAINS SQL
                SQL_PATH: NULL
           SECURITY_TYPE: DEFINER
                 CREATED: 2022-09-22 03:29:02
            LAST_ALTERED: 2022-09-22 03:29:02
                SQL_MODE: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
         ROUTINE_COMMENT: 
                 DEFINER: root@localhost
    CHARACTER_SET_CLIENT: utf8mb4
    COLLATION_CONNECTION: utf8mb4_0900_ai_ci
      DATABASE_COLLATION: utf8mb4_0900_ai_ci

以上是关于Linux学习-存储过程及函数的主要内容,如果未能解决你的问题,请参考以下文章

Oracle-存储过程与函数

SqlServer存储过程及函数

PL/SQL学习笔记_03_存储函数与存储过程

分析Linux内核创建一个新进程的过程

Java学习总结(十八)——MySQL数据库MySQL数据库中的视图,函数,存储过程中常见循环

mysql 与oracle中的存储过程及函数有啥区别,尽可能详细哦