MYSQL的储存过程的学习

MYSQL的储存过程

储存过程的创建、修改、删除、调用

创建储存过程

语法:
    CREATE PROCEDURE proc_name ([proc_parameter]) [characteristics...] body
讲解:
    CREATE PROCEDURE:创建存储过程关键字
    proc_name:存储过程名称
    proc_parameter:参数列表,可选,格式:[IN | OUT | INOUT] param_name type
        IN:输入参数
        OUT:输出参数
        INOUT:既可以输入也可以输出
        param_name:参数名称
        type:参数类型,MySQL中的任意类型,如varchar等
    characteristics:指定存储过程特性,取值如下:
        LANGUAGE SQL:说明body部分由SQL语句组成,LANGUAGE可选值只有SQL
        [NOT] DETERMINISTIC:指明存储过程执行结果是否确定。默认值:NOT DETERMINISTIC
            DETERMINISTIC:结果确定,每次执行存储过程时,相同的输入会得到相同的输出
            NOT DETERMINISTIC:结果不确定,相同输入可能得到不同输出。
        {CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA}:指定子程序使用存储过程的限制。默认值:CONTAINS SQL
            CONTAINS SQL:说明子程序包含SQL语句,但是不包含写数据语句
            NO SQL:说明子程序不包含SQL语句
            READS SQL DATA:说明子程序包含读数据读数据语句
            MODIFIES SQL DATA:说明子程序包含写数据语句
        SQL SECURITY {DEFINER | INVOKER}:指明谁有权限执行,默认值:DEFINER
            DEFINER:只有定义者才能执行
            INVOKER:拥有权限的调用者才可以执行
        COMMNET:注释信息

创建调用

语法:
    CALL proc_name ([parameter[,...]])
案例:
    DELIMITER $$
    CREATE PROCEDURE proc_countByName(IN uname VARCHAR(100), OUT total INT)
    BEGIN
        SELECT COUNT(*) INTO total FROM njit_user WHERE NAME LIKE CONCAT('%', uname, '%');
    END $$

删除存储过程

语法:
    DROP {PROCEDURE | FUNCTION} [IF EXISTS] proc_name
删除:
    DROP PROCEDURE  proc_countByName;
    DROP PROCEDURE IF EXISTS proc_countByName;

修改

语法:
    ALTER {PROCEDURE | FUNCTION} proc_or_func [characterustic...]
说明:
    {CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA}:指定子程序使用存储过程的限制。
        CONTAINS SQL:说明子程序包含SQL语句,但是不包含写数据语句
        NO SQL:说明子程序不包含SQL语句
        READS SQL DATA:说明子程序包含读数据读数据语句
        MODIFIES SQL DATA:说明子程序包含写数据语句
    SQL SECURITY {DEFINER | INVOKER}:指明谁有权限执行,默认值:DEFINER
        DEFINER:只有定义者才能执行
        INVOKER:拥有权限的调用者才可以执行
    COMMNET:注释信息

查看状态

语法:
    SHOW {PROCEDURE | FUNCTION} STATUS [LIKE 'parttern']
说明:
    这个语句是MySQL的扩展,它返回子程序的特征,如数据库、名字、类型、创建者及创建和修改日期。如果没有指定样式,根据使用的语句,所有存储程序或存储函数的信息都被列出。PROCEDURE和FUNCTION分别表示查看存储过程和函数;LIKE语句表示匹配存储过程或函数名称。
案例:
    SHOW PROCEDURE STATUS LIKE 'proc_%';

储存过程的基础命令

### 创建存储过程
-- 定义结束符[为了PROCEDURE的结束符与mysql的普通语句不同]
delimiter //
-- 如果该储存过程存在就删除
DROP PROCEDURE IF EXISTS in_param;
-- 创建一个储存过程[in_param],需要传入参数inParam
CREATE PROCEDURE in_param(INOUT inParam VARCHAR(50))
-- 开始标识符
BEGIN
-- 定义变量
DECLARE var_param1 VARCHAR(50) DEFAULT "自定义变量默认值var_param1";
     -- 获取数据值
     SELECT var_param1;
     -- 重新改变数据值
     SET var_param1='改变自定义的属性值';
     -- 获取数据值
     SELECT var_param1;
     -- 重新赋值
     select "运行into储存值" into intoParam;
     select intoParam;
     -- 语句执行结束符
END //
-- 重新改变数据的结束的标识符
delimiter ;



### 调用存储过程
语法:call sp_name()
注意:存储过程名称后面必须加括号,哪怕该存储过程没有参数传递



### 删除存储过程
语法:drop procedure sp_name
注意:不能在一个存储过程中删除另一个存储过程,只能调用另一个存储过程

储存过程的简单使用案例

-- 定义结束符[为了PROCEDURE的结束符与mysql的普通语句不同]
delimiter //
-- 如果该储存过程存在就删除
DROP PROCEDURE IF EXISTS in_param;
-- 创建一个储存过程[in_param],需要传入参数inParam
CREATE PROCEDURE in_param(INOUT inParam VARCHAR(50))
-- 开始标识符
BEGIN
-- 定义变量
DECLARE var_param1 VARCHAR(50) DEFAULT "自定义变量默认值var_param1";
DECLARE intoParam VARCHAR(50) DEFAULT "自定义变量默认值intoParam";
     -- 获取数据值
     SELECT var_param1;
     SELECT inParam;
     -- 重新改变数据值
     SET var_param1='改变自定义的属性值';
     SET inParam='传入值的修改';
     -- 获取数据值
     SELECT var_param1;
     SELECT inParam;
     -- 重新赋值
     select "运行into储存值" into intoParam;
     select intoParam;
     -- 语句执行结束符
END //
-- 重新改变数据的结束的标识符
delimiter ;
 
 
 
-- 调用储存过程[储存过程是传入的参数当我们select @inParamStr输出的是原始值,而不是过程内部修改之后的值,如果我们更改参数类型为inout,则会输出]
set @inParamStr="传入参数";
CALL in_param(@inParamStr);
select @inParamStr;

储存过程的变量的定义

变量的定义
   DECLARE [相同属性的变量x ......] VARCHAR(50) DEFAULT "默认的初始化值";
改变变量值
   SET x= "修改之后的值";
改变变量值
   select "查询改变之后的值" into x;

变量范围(作用域)

一个变量有自己的范围(作用域),它用来定义它的生命周期。 如果在存储过程中声明一个变量,那么当达到存储过程的END语句时,它将超出范围,因此在其它代码块中无法访问。
如果您在BEGIN END块内声明一个变量,那么如果达到END,它将超出范围。 可以在不同的作用域中声明具有相同名称的两个或多个变量,因为变量仅在自己的作用域中有效。 但是,在不同范围内声明具有相同名称的变量不是很好的编程习惯。
以@符号开头的变量是会话变量。直到会话结束前它可用和可访问。

定义条件和处理程序

#定义条件
    语法:DECLARE cond_name CONDITION FOR [cond_type]
    解析:[cond_type]:SQLSTATE [VALUE] sqlstate_value(可选项) | mysql_erroe_code(可选项)
         cond_name:条件名称
         cond_type:条件类型,用于定义MySQL的错误,SQLSTATE是长度为5的字符串类型的错误代码;mysql_error_code是数值类型的错误代码。例如ERROR 1142(42000),sql_state_value的值是'42000',mysql_error_code的值是1142。
         
    示例:
        -- 使用SQLSTATE
        DECLARE cond_error CONDITION FOR SQLSTATE '42000';
        -- 使用mysql_error_code
        DECLARE cond_error CONDITION FOR 1148;

#定义处理程序
    语法:DECLARE handler_type HANDLER FOR  condition_value[,...] sp_statement
    解析:handler_type:指定错误处理方式
            CONTINUE:遇到错误不处理,继续执行
            EXIT:遇到错误立即退出
            UNDO:遇到错误撤回之前的操作
         condition_value:表示错误类型
            SQLSTATE [VALUE] sqlstate_value:包含5个字符的字符串错误值
            mysql_error_code:数值类型的错误代码
            cond_name:定义条件的名称,见第一节
            SQLWARNING:匹配所有以01开头的SQLSTATE错误代码
            NOT FOUND:匹配所有以02开头的SQLSTATE错误代码
            SQL EXCEPTION:匹配所有没有被SQLWARNING或NOT FOUND捕获的SQLSTATE错误代码
         sp_statement: 程序语句段
            程序语句段,表示在遇到定义的错误时执行的存储过程或函数。
    
    示例:
        -- 捕获SQLSTATE
        DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET @info='NO_SUCH_TABLE';
        -- 捕获mysql_error_code
        DECLARE CONTINUE HANDLER FOR SQLSTATE '1146' SET @info='NO_SUCH_TABLE' ;
        -- 捕获定义条件
        DECLARE no_such_table CONDITION FOR 1146;
        DECLARE CONTINUE HANDLER FOR no_such_table SET @info='NO_SUCH_TABLE';
        -- 捕获SQLWARNING
        DECLARE EXIT HANDLER FOR SQLWARNING set @info='ERROR';
        -- 捕获NOT FOUND
        DECLARE EXIT HANDLER FOR NOT FOUND set @info='NO_SUCH_TABLE';
        -- 捕获SQLEXCEPTION
        DECLARE EXIT HANDLER FOR SQLEXCEPTION set @info='ERROR';
        -- 捕获所有异常
        DECLARE EXIT HANDLER FOR SQLWARNING, NOT FOUND,SQLEXCEPTION BEGIN ... END;



#存储过程示例
DELIMITER $$
CREATE PROCEDURE proc_del_user(IN uid INT, OUT rowCount INT, OUT msg VARCHAR(200))
BEGIN
	-- 出错标记
	DECLARE t_error INT DEFAULT 0;
	-- 定义出错处理程序
	DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET t_error = 1;
	
	-- 删除用户
	DELETE FROM t_user WHERE id = uid;
	
	-- 异常处理
	IF t_error = 0 THEN
		SET msg = 'success';
	ELSE
		SET msg = 'error';
	END IF;
	
	-- 设置真正影响行数的行数,修改了但是没有修改值都不计入
	SET rowCount = ROW_COUNT();
	SELECT rowCount, msg;
END $$

-- 调用储存过程
CALL proc_del_user(1, @rowCount, @msg);
SELECT @rowCount, @msg;

光标的使用

光标:查询语句可能查询出多条记录,在存储过程和函数中使用光标来逐条读取查询结果集中的记录
步骤:声明光标->打开光标->使用光标->关闭光标;
     光标必须声明在处理程序之前,并且声明在变量和条件之后。
     
语法:
    声明光标:DECLARE cursor_name CURSOR FOR select_statement(sql命令); 
            cursor_name参数表示光标的名称;select_statement参数表示SELECT语句的内容,返回一个用于创建光标的结果集
    打开光标:OPEN  cursor_name;
            cursor_name参数表示光标的名称。
    使用光标:FETCH cur_employee INTO var_name[,var_name…] ; 
            cursor_name参数表示光标的名称;var_name参数表示将光标中的SELECT语句查询出来的信息存入该参数中。var_name必须在声明光标之前就定义好
    关闭光标:CLOSE  cursor_name ; 
            cursor_name参数表示光标的名称。关闭之后就不能使用FETCH来使用光标了
            
            
例子:
   begin 
    ##定义变量
    declare my_id varchar(32); 
    declare my_name varchar(50); 
    DECLARE done INT DEFAULT FALSE; 
    #创建游标并存储数据,
    DECLARE My_Cursor CURSOR FOR ( SELECT tid,tname FROM `teacher` ); 
    #游标中内容执行完设置done为1
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; 
    #设置手动提交
    set autocommit=0;
    #打开游标
    OPEN My_Cursor; 
    #执行循环
      myLoop: LOOP 
    #判断是否结束循环
        IF done THEN 
          LEAVE myLoop; 
        END IF;
    #取出游标中的值
        FETCH My_Cursor into my_id,my_name; 
    #更新数据
        UPDATE course SET cname = my_name WHERE teacher_id = my_id ; 
    
    
      END LOOP myLoop; 
    #释放游标
      CLOSE My_Cursor; 
     #提交
        COMMIT; 
    END

流程控制

流程控制:[IF语句、CASE语句、LOOP语句、LEAVE语句、ITERATE语句、REPEAT语句、WHILE]
语法:
    IF语句:[类似于java的if-else if-else]search_condition参数表示条件判断语句;statement_list参数表示不同条件的执行语句[MYSQL还有一个IF()函数,他不同于这里描述的IF语句]
        语法:
            IF search_condition THEN statement_list 
            [ELSEIF search_condition THEN statement_list] ... 
            [ELSE statement_list] 
            END IF
        案例:
            IF age>20 THEN SET @count1=@count1+1;  
            ELSEIF age=20 THEN SET @count2=@count2+1;  
            ELSE SET @count3=@count3+1;  
            END IF; 
    CASE语句:[类似于java的switch]case_value参数表示条件判断的变量;when_value参数表示变量的取值;statement_list参数表示不同when_value值的执行语句
        语法:
            CASE case_value 
            WHEN when_value THEN statement_list 
            [WHEN when_value THEN statement_list] ... 
            [ELSE statement_list] 
            END CASE 
        案例:
            CASE age 
            WHEN 20 THEN SET @count1=@count1+1; 
            ELSE SET @count2=@count2+1; 
            END CASE ; 
    CASE另一种写法:[类似于java的switch]CASE search_condition参数表示条件判断语句;statement_list参数表示不同条件的执行语句;
        语法:
            WHEN search_condition THEN statement_list 
            [WHEN search_condition THEN statement_list] ... 
            [ELSE statement_list] 
            END CASE 
        案例:
            CASE 
            WHEN age=20 THEN SET @count1=@count1+1; 
            ELSE SET @count2=@count2+1; 
            END CASE;
        注意:注意:这里的CASE语句和“控制流程函数”里描述的SQL CASE表达式的CASE语句有轻微不同。这里的CASE语句不能有ELSE NULL子句并且用END CASE替代END来终止!!
    LOOP语句:[类似于java的for]LOOP语句可以使某些特定的语句重复执行,实现一个简单的循环,但是LOOP语句本身没有停止循环的语句,必须是遇到LEAVE语句等才能停止循环
        语法:begin_label参数和end_label参数分别表示循环开始和结束的标志,这两个标志必须相同,而且都可以省略;statement_list参数表示需要循环执行的语句
            [begin_label:] LOOP 
            statement_list 
            END LOOP [end_label] 
        案例:因为没有跳出循环的语句,这个循环成了一个死循环
            add_num: LOOP  
            SET @count=@count+1;  
            END LOOP add_num ; 
    LEAVE语句:[类似于java的return]LEAVE语句主要用于跳出循环控制
        语法:label参数表示循环的标志
            LEAVE label
        案例:
            add_num: LOOP 
            SET @count=@count+1; 
            IF @count=100 THEN 
            LEAVE add_num ; 
            END LOOP add_num ;
    ITERATE语句:[类似于java的continue]ITERATE语句也是用来跳出循环的语句。但是,ITERATE语句是跳出本次循环,然后直接进入下一次循环;ITERATE语句只可以出现在LOOP、REPEAT、WHILE语句内
        语法:label参数表示循环的标志
            ITERATE label
        案例:
            add_num: LOOP 
            SET @count=@count+1; 
            IF @count=100 THEN 
            LEAVE add_num ; 
            ELSE IF MOD(@count,3)=0 THEN 
            ITERATE add_num; 
            SELECT * FROM employee ; 
            END LOOP add_num ; 
    REPEAT语句:[类似于Java的do-while]REPEAT语句是有条件控制的循环语句。当满足特定条件时,就会跳出循环语句
        语法:statement_list参数表示循环的执行语句;search_condition参数表示结束循环的条件,满足该条件时循环结束
            [begin_label:] REPEAT 
            statement_list 
            UNTIL search_condition 
            END REPEAT [end_label] 
        案例:
            REPEAT 
            SET @count=@count+1; 
            UNTIL @count=100 
            END REPEAT ; 
    WHILE语句:[类似于Java的while]WHILE语句也是有条件控制的循环语句。但WHILE语句和REPEAT语句是不一样的。WHILE语句是当满足条件时,执行循环内的语句
        语法:search_condition参数表示循环执行的条件,满足该条件时循环执行,statement_list参数表示循环的执行语句
            [begin_label:] WHILE search_condition DO 
            statement_list 
            END WHILE [end_label]
        案例:
            WHILE @count<100 DO 
            SET @count=@count+1; 
            END WHILE ; 
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值