存储过程和函数
    存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句的集合.
    调用存储过程和函数可以简化应用开发人员的工作,减少数据在数据库和应用服务器之间的传输,提高数据处理的效率.
 
    存储过程和函数的区别在于:
        函数必须有返回值,而存储过程没有.
        存储过程的参数可以使用 IN,OUT,INOUT 类型;而函数的参数只能是IN类型.
     
    如果有函数从其他类型数据库迁移到MySQL就可能需要把函数改造成存储过程.
 
 
存储过程和函数的相关操作
    首先确认是否有相应的权限.
        创建存储过程/函数 需要CREATE ROUTINE权限.
        修改/删除 存储过程/函数 需要ALTER ROUTINE权限.
        执行存储过程/函数 需要EXECUTE权限.
 
    1).创建/修改 存储过程或函数
        CREATE PROCEDURE sp_name ([proc_param[,...]])
            [characteristic …] 
            routine_body
 
        CREATE FUNCTION sp_name ([func_param[,...])
            RETURNS     type
            [characteristic …] 
            routine_body
 
 
            其中,
            proc_param :
                [IN|OUT|INOUT] param_name type
 
            func_param :
                param_name type
 
            type : any valid MySQL data type .
    
            characteristic :
                LANGUAGE SQL
                | [NOT] DETERMINISTIC
                | {CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA}
                | SQL SECURITY {DEFINER | INVOKER}
                | COMMENT 'string'
 
            routine_body :
                valid SQL procedure statement or statements .
 
        
 
        ALTER {PROCEDURE | FUNCTION} sp_name [characteristic ...]
 
        characteristic :
            {CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA}
            |SQL SECURITY {DEFINER|INVOKER}
            |COMMENT 'string'
 
        调用存储过程/函数,使用关键字CALL :
            CALL sp_name ([[parameter [,...]])
 
 
      注意: 存储过程/函数 中允许包含DDL ,也可以在存储过程中执行COMMIT/ROLLBACK 操作,还可以调用其他的过程/函数;
                但是存储过程/函数 中不允许使用 LOAD DATA INFILE 语句.
 
 
           Demo :
                DELIMITER $$
        
                CREATE PROCEDURE film_in_stock (IN p_film_id INT , IN p_store_id INT , OUT p_film_count INT)
                READS SQL DATA
                BEGIN
                        SELECT inventory_id
                        FROM inventory
                        WHERE film_id = p_film_id
                        AND store_id = p_store_id
                        AND inventory_in_stock(inventory_id);
        
                        SELECT FOUND_ROWS() INTO p_film_count;
                END $$
 
                DELIMITER ;
 
                CALL film_in_stock(2,2,@a);
        
                SELECT @a ;
 
    注意 : 与视图的创建语法不同,存储过程/函数 的CREATE语法不支持使用 CREATE OR REPLACE对存储过程/函数进行修改.如需修改,可以执行ALTER语法.
 
 
 
    characteristic特征值的简单说明:
 
        1).LANGUAGE SQL
            说明下面过程的BODY是使用SQL语句编写(系统默认的),以后MySQL可能支持其它语言.
 
        2).[NOT] DETERMINISTIC:
                目前还未被优化程序使用
                DETERMINISTIC 每次输入一样输出也一样的程序
                NOT DETERMINISTIC(系统默认).
 
        3).{CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA}
            目前这些特征值只是提供给服务器,并未用来约束存储过程实际使用数据的情况.
                CONTAINS SQL 表示子程序不包含读或者写数据的语句
                NO SQL 表示子程序不包含SQL语句
                READS SQL DATA 表示子程序包含读数据的语句
                MODIFIES SQL DATA 表示子程序包含写数据的语句
                默认值是 CONTAINS SQL
 
        4).SQL SECURITY {DEFINER | INVOKER}
            指定子程序 该用创建子程序者的权限来执行,还是使用调用者的权限来执行.默认值是DEFINER , 即使用创建者的权限执行.
 
        5).COMMENT 'string'
            存储过程/函数 的注释信息.
 
 
    
    2.删除存储过程/函数
        一次性只能删除一个存储过程/函数.需要有ALTER ROUTINE 权限.
        DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name
 
 
    3.查看存储过程/函数
        1).查看存储过程/函数 的状态
            SHOW {PROCEDURE | FUNCTION} STATUS [LIKE 'pattern']
 
        2).查看存储过程/函数 的定义
            SHOW CREATE {PROCEDURE|FUNCTION} sp_name
 
        3).通过查看information_schema.Routines 了解存储过程/函数 的信息
            包含名称,类型,语法,创建人等信息.
            demo:SELECT * FROM routines WHERE ROUTINE_NAME = 'film_in_stock' \G
 
    
    4.变量的使用
 
        1).变量的定义
            DECLARE var_name [,...] type [DEFAULT value]
 
 
        2).变量的赋值
            SET var_name = expr [,var_name = expr] ...
 
            其中,expr 可以是字面量,函数返回值,SELECT 语句(要求结果有且只有一行)等.
            或者使用SELECT .. INTO .. 语句
            SELECT col_name[,..] INTO var_name[,..] table_expr
 
             Demo :
 
                DECLARE $$
 
        CREATE FUNCTION get_customer_balance( p_customer_id INT , p_effective_date DATETIME )
            RETURNS DECIMAL(5,2)
            DETERMINISTIC
            READS SQL DATA
        BEGIN
                ...
                DECLARE v_payments DECIMAL(5,2) ;
                ...
                SELECT IFNULL (SUM(payment,amount),0) INTO v_payments
                FROM payment
                WHERE payment.payment_date <= p_effective_date
                AND payment.customer_id = p_customer_id ;
                ...        
                RETURN v_rentfees + v_overfees - v_payments ;
        END $$
        DECLARE ;
 

CALL get_customer_balance(1,'2018-03-02 09:11:15') ;

            
 
 
    5.定义条件和处理
        1).条件的定义
            DECLARE condition_name CONDITION FOR condition_value
 
            其中,condition_value :
                SQLSTATE [VALUE] sqlstate_value | mysql_error_code
 
        2).条件的处理
            DECLARE handler_type HANDLER FOR condition_value[,..] sp_statement
 
            handler_type :
                CONTINUE | EXIT | UNDO(暂不支持)
 
            condition_value:
                SQLSTATE [VALUE] sqlstate_value
                |condition_name
                |SQLWARNING
                |NOT FOUND
                |SQLEXCEPTION
                |mysql_error_code
 
 
        demo:todo
 
 
 
    6.光标的使用 --就是游标
        可以使用游标对结果集进行循环处理
        1).声明光标
            DECLARE cursor_name CURSOR FOR select_statement
                select_statement 中的SELECT语句 不能包含 INTO , 即不可以是SELECT .. INTO ..语句
                SELECT 语句查询出来的列数 , 必须与FETCH游标中的接收数据的变量数 一致.     
 
        2).OPEN光标
            OPEN cursor_name
 
        3).FETCH光标
            FETCH cursor_name INTO var_name[,var_name,..]
 
        4).CLOSE光标
            CLOSE cursor_name
 
        Demo :  —— 需要注意 DECLARE 声明的顺序 : 变量 -> 游标 -> 条件处理 .
            DELIMITER $$
        
            CREATE PROCEDURE payment_stat()
            BEGIN
                DECLARE i_staff_id INT ;
                DECLARE d_amount DECIMAL(5,2);
                DECLARE cur_payment CURSOR FOR SELECT staff_id,amount FROM payment ;
                DECLARE EXIT HANDLER FOR NOT FOUND CLOSE cur_payment ;
 
                SET @x1 = 0 ;
                SET @x2 = 0 ;
 
                OPEN cur_payment ;
                
                REPEAT
                    FETCH cur_payment INTO i_staff_id,d_amount ;
                        IF i_staff_id = 2
                        THEN
                            SET @x1 = @x1 + d_amount ;
                        ELSE
                            SET @x2 = @x2 + d_amount ;
                        END IF ;
                UNTIL 0 END REPEAT ;
 
                CLOSE cur_payment ;
 
            END ;
            $$
 
            DELIMITER ;
 
            CALL payment_stat();
 
        注意:变量,条件,处理程序,游标都是通过DECLARE定义的,但是顺序是由先后要求的.
            变量和条件 必须声明在最前面,然后是游标的声明,最后才是处理程序的声明.
 
 
 
    7.流程控制
        1).IF语句
 
            IF search_condition
                THEN statement_list
            [
            ELSEIF search_condition 
                THEN statement_list
            ]
            [
            ELSE statement_list
            ]
            END IF
 
        2).CASE语句
            CASE case_value
                WHEN when_value THEN
                     statement_list
                [
                WHEN when_value THEN
                     statement_list
                ]
                    ...
                [
                ELSE 
                    statement_list
                ]
            END CASE
 
           或者
            CASE WHEN search_condition THEN 
                    statement_list
                [
                WHEN search_condition THEN
                     statement_list
                ]
                    ...
                [
                ELSE 
                    statement_list
                ]
            END CASE
 
        Demo : 改写游标demo中IF语句
            
            CASE
                WHEN i_staff_id = 2
                 THEN
                    SET @x1=@x1+d_amount ;
                ELSE
                    SET @x2= @x2+d_amount ;
            END CASE ;
 
           或
            CASE i_staff_id
                WHEN 2
                THEN
                    SET @x1 = @x1 + d_amount ;
                ELSE
                    SET @x2 = @x2 + d_amount ;
            END CASE ;
 
 
        3).LOOP 语句
            简单的循环,需要配合其他的语句定义来实现退出循环,通常使用LEAVE语句实现.
 
            [begin_label:] LOOP
                statement_list
            END LOOP [end_label]
 
            如果没有退出循环语句,就是个死循环.
 
 
        4).LEAVE 语句
            从标注的流程中退出,通常和BEGIN..END / 循环 一起使用.
            Demo :
 
                DELIMITER $$
 
                CREATE PROCEDURE actor_insert()
                BEGIN
                    SET @x = 0 ;
                    ins : LOOP
                        SET @x = @x+1;
                        IF @x=100
                        THEN
                            LEAVE ins ;
                        END IF ;
                        INSERT INTO actor(first_name,last_name)
                        VALUES('Test','201');
                    END LOOP ins ;
                END ;
                $$
 
                DELIMITER ;
 
                CALL actor_insert();
 
 
        5).ITERATE 语句
            必须用在循环中,表示跳过当前循环的剩下语句,进入下次循环.作用相当于Java中的continue.
 
            Demo:
            
                DELIMITER $$
                CREATE PROCEDURE actor_insert()
                BEGIN
                    SET @x = 0 ;
                    ins : LOOP
                        SET @x = @x + 1;
                        IF @x = 10
                        THEN
                            LEAVE ins ;
                        ELSEIF mod(@x,2) = 0
                        THEN
                            ITERATE ins ;
                        END IF ;
                        INSERT INTO actor (actor_id , first_name,last_name)
                        VALUES(@x*10,'Test',@x);
                    END LOOP ins ;
                END ;
                $$
 
                DELIMITER ;
            
                CALL actor_insert() ;
 
        6).REPEAT 语句
            有条件的循环语句,相当于Java中的do_while
            不同的是REPEAT是满足条件时就退出循环,while是满足就执行.Repeat 和 do..while 一样,至少执行一次.
 
                Demo参考游标的demo
 
 
        
        7).WHILE 语句
            [begin_label:] WHILE search_condition
                DO statement_list
            END WHILE [end_label]
 
    
    总结:存储过程/函数的优势是可以将数据的处理放在数据库服务器上进行,避免将大量的结果集传输给客户端,减少数据传输,
            但是在数据库服务器上进行大量的复杂运算会占用服务器的cpu,造成数据库服务器的压力,
            所以存储过程/函数中不要进行大量的复杂运算,应该将这些运算操作分摊到应用服务器上执行.
     

12 MySQL存储过程与函数的更多相关文章

  1. 12.Mysql存储过程和函数

    12.存储过程和函数12.1 什么是存储过程和函数存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句的集合,调用存储过程和函数简化应用开发人员的工作,减少数据在数据库和应用服务器之间的传输, ...

  2. MYSQL存储过程和函数学习笔记

    学至Tarena金牌讲师,金色晨曦科技公司技术总监沙利穆课程笔记的综合. 1. 什么是存储过程和函数 将SQL语句放入一个集合里,然后直接调用存储过程和函数来执行已经定义好的SQL语句,通过存储过程和 ...

  3. Paip.断点调试MYSQL存储过程跟函数的解决方案大法

    Paip.断点调试MYSQL存储过程跟函数的解决方案大法 作者Attilax ,  EMAIL:1466519819@qq.com  来源:attilax的专栏 地址:http://blog.csdn ...

  4. Mysql存储过程和函数

    Mysql存储过程和函数 基本概念: 创建存储过程和函数是指将经常使用的一组SQL语句的组合在一起,并将这些SQL语句当作一个整体存储在MySQL服务器中.例如,银行经常需要计算用户的利息.不同类别的 ...

  5. MySql存储过程与函数详解

    存储过程和函数是在数据库中定义一些SQL语句的集合,然后直接调用这些存储过程和函数来执行已经定义好的SQL语句.存储过程和函数可以避免开发人员重复的编写相同的SQL语句.而且,存储过程和函数是在MyS ...

  6. mysql 存储过程,函数,触发器

    存储过程和函数 mysql> HELP CREATE PROCEDURE; Name: 'CREATE PROCEDURE' Description: Syntax: CREATE [DEFIN ...

  7. MySql存储过程、函数

    存储过程和函数是在数据库中定义一些SQL语句的集合,然后直接调用这些存储过程和函数来执行已经定义好的SQL语句.存储过程和函数可以避免开发人员重复的编写相同的SQL语句.而且,存储过程和函数是在MyS ...

  8. Mysql - 存储过程/自定义函数

    在数据库操作中, 尤其是碰到一些复杂一些的系统, 不可避免的, 会用到函数/自定义函数, 或者存储过程. 实际项目中, 自定义函数和存储过程是越少越好, 因为这个东西多了, 也是一个非常难以维护的地方 ...

  9. MySQL 存储过程和函数

    概述 一提到存储过程可能就会引出另一个话题就是存储过程的优缺点,这里也不做讨论,一般别人问我我就这样回答你觉得它好你就用它.因为mysql中存储过程和函数的语法非常接近所以就放在一起,主要区别就是函数 ...

随机推荐

  1. StringBuilder为什么线程不安全(面试必问)

    文章转载自:https://juejin.im/post/5d6228046fb9a06add4e37fe 作者:千山qianshan 1.引言 周五去面试又被面试的一个问题问哑巴了 面试官:Stri ...

  2. LeetCode 141. Linked List Cycle(判断链表是否有环)

    题意:判断链表是否有环. 分析:快慢指针. /** * Definition for singly-linked list. * struct ListNode { * int val; * List ...

  3. windows系统桌面美化

    系统主题:https://zhutix.com/ 壁纸:https://wallhaven.cc/

  4. SSM(Spring-SpringMvc-Mybatis)练习

    1.总结 https://pan.baidu.com/s/1kXlCf4r  密码:hv6v 2.代码 https://pan.baidu.com/s/1pNgKph5  密码:6rcm 3.资料 h ...

  5. 《精通iOS开发》书籍目录

    1.欢迎来到iOS和Swift世界 2.创建一个新项目 3.实现基本交互 4.更丰富的用户界面 5.自动旋转和自动调整大小 6.多视图应用 7.分页栏与选取器 8.表视图简介 9.导航控制器和表视图 ...

  6. keep-alive的使用

    <keep-alive>是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM. <router-view>中间为组件</router-view&g ...

  7. 简单易懂之python 中的map,filter,reduce用法

    map(function,sequence) 把sequence中的值当参数逐个传给function,返回一个包含函数执行结果的list. 重点是结果返回一个列表,这样对返回的列表就可以干很多的活了. ...

  8. 第1节 storm编程:9、storm与kafka的整合

    详见代码. 下图,为设置kafka的首次消费策略,即首次消费的偏移量的示例:

  9. Lognormal distribution 对数正态分布

    转载:https://blog.csdn.net/donggui8650/article/details/101556041 在概率论中,对数正态分布是一种连续概率分布,其随机变量的对数服从正态分布. ...

  10. 【MAVEN】maven项目下载更新pom jar包速度慢 解决方案

    1·下载安装 最新版本的maven https://maven.apache.org/download.cgi 2·速度慢的主要原因是因为默认setting.xml里配置的国外的 maven 数据源 ...