• 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)
    
  • 相关阅读:
    数据库表数据传输到Oracle方案
    Pdnovel 在线阅读体验
    Metaweblog博客分发体验
    Liveqrcode活码系统设计
    Java Language Changes for Java SE 9
    利用“计算器”和公式做房贷计算
    阿里云SLB快速切换至https
    Charles 协助解决 metaweblog 排序问题
    Go语言网络通信---连续通信的UDP编程
    Go语言网络通信---一个简单的UDP编程
  • 原文地址:https://www.cnblogs.com/tongxiaoda/p/8022418.html
Copyright © 2020-2023  润新知