存储过程详解

时间:2022-01-28 14:04:32
        MySQL数据库在5.0版本后开始支持存储过程,那么什么是存储过程呢?怎么创建、查看和删除存储过程呢?存储过程有什么优点?这些是本章节要探讨的问题:
        什么是存储过程:
        简单的说存储过程是为了完成某个数据库中的特定功能而编写的语句集,该语句集包括SQL语句(对数据的增删改查)、条件语句和循环语句等。
        创建存储过程

        存储过程的创建非常简单,其创建结构为:

CREATE PROCEDURE proc_name ([proc_parameter[,...]])  [characteristic] 
routine_body
        说明:
        proc_name代表存储过程名称;

        proc_parameter代表存储过程参数列表。该列表中的每个参数由3部分组成,即输入输出类型、参数名称和参数类型。其形式如下: [ IN | OUT | INOUT ] param_name type ,其中[ IN | OUT | INOUT ]表示输出类型(IN表示输入参数;OUT表示输出参数; INOUT表示既可以是输入,也可以是输出。输入输出类型也可以去掉,默认为in); param_name表示参数名称(注意:MySQL数据库存储过程的参数名前不允许“@”,SQL Server数据库中可以);type表示参数类型,该类型可以是MySQL数据库的任意数据类型。

        注意:MySQL数据库存储过程不需要在参数列表括号后面“as”关键字,但SQL Server数据库中的存储过程必须加“as”关键字。

        characteristic指定存储过程的特性;该参数有多个值:
                LANGUAGE SQL:说明routine_body部分是由SQL语言的语句组成,数据库系统默认值。
                [NOT] DETERMINISTIC:指明存储过程的执行结果是否是确定的。DETERMINISTIC表示结果是确定的,这时当每次执行存储过程时相同的输入会得到相同的输出。NOT DETERMINISTIC表示结果是非确定的,这时相同的输入可能得到不同的输出。默认为非确定。
                { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }:指明子程序使用SQL语句的限制。CONTAINS SQL表示子程序包含SQL语句,但不包含读或写数据的语句;NO SQL表示子程序中不包含SQL语句;READS SQL DATA表示子程序中包含读数据的语句;MODIFIES SQL DATA表示子程序中包含写数据的语句。默认为CONTAINS SQL。
                SQL SECURITY { DEFINER | INVOKER }:指明谁有权限来执行。DEFINER表示只有定义者自己才能够执行;INVOKER表示调用者可以执行。默认为DEFINER。
                COMMENT 'string':存储过程注释信息。

        routine_body参数为存储过程体,BEGIN…END标志存储过程体的开始和结束。存储过程体可以是SELECT、UPDATE、INSERT、DELETE、CREATE TABLE等SQL语句,也可以嵌入调用其它存储过程的代码,还可以是其它代码(参见博客:《数据库中的控制语句》)。

        注意:不能在 MySQL 存储过程中使用 “return” 关键字。

        示例一——使用存储过程创建表结构:
        创建存储过程:

DELIMITER &&   CREATE PROCEDURE create_table ()   LANGUAGE SQL   BEGIN   CREATE TABLE `user` (     `id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键',     `real_name` VARCHAR(8) NOT NULL COMMENT '姓名',     `age` INT(3) DEFAULT NULL COMMENT '年龄',     PRIMARY KEY (`id`)) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;END &&   DELIMITER ;
        说明:上面创建了一个名称为create_table的存储过程;

        注意:MySQL中默认的语句结束符为分号(;),存储过程中的SQL语句需要分号来结束,为了避免冲突,首先用"DELIMITER &&"将MySQL的结束符设置为&&,最后再用"DELIMITER ;"来将结束符恢复成分号。这与创建触发器是一样的。

        调用存储过程:

CALL create_table();
        示例二——向创建好的表中添加数据:

        创建存储过程:

DELIMITER &&     CREATE PROCEDURE insert_data (IN u_real_name VARCHAR(8), IN u_age INT(3), OUT u_id INT(11))     LANGUAGE SQL     BEGIN   INSERT INTO USER (real_name, age)VALUES(u_real_name, u_age);  SET u_id=LAST_INSERT_ID();#或SET u_id=@@IDENTITY;END &&     DELIMITER ;

        说明:上面创建的存储过程参数列表中u_real_name和u_age为输入变量,u_id为输出变量,该输出变量返回所添加数据对应的主键值;

        调用存储过程:

CALL insert_data('小明',21, @u_id);  SELECT @u_id;

        示例三——修改表中的数据:
        创建存储过程:
DELIMITER &&   CREATE PROCEDURE update_data (IN u_id INT(11),IN u_real_name VARCHAR(8), IN u_age INT(3))   LANGUAGE SQL   BEGIN UPDATE USER SET real_name = u_real_name, age = u_age WHERE id = u_id;END &&   DELIMITER ;
        调用存储过程:
CALL update_data(1,'王佳佳',18);
        示例四——依据姓名进行模糊查询获得符合条件的人数:
        创建存储过程:

DELIMITER && CREATE PROCEDURE num_from_user (IN u_real_name VARCHAR(15), OUT count_num INT) READS SQL DATA BEGIN SELECT COUNT(*) INTO count_num FROM USER WHERE real_name LIKE u_real_name; END && DELIMITER ;
        说明:上面创建的存储过程参数列表中u_real_name为输入变量;count_num为输出变量。
SELECT语句从user表模糊查询real_name值等于u_real_name的记录,并用COUNT(*)统计符合条件的数据总数,然后将结果存入count_num中。
        调用存储过程:
SET @u_real_name='王%';  CALL num_from_user(@u_real_name,@count_num); SELECT @count_num AS total;

        说明:上面显示姓王的人数,其中@u_real_name和@count_num为用户名变量。

        示例五——依据主键id删除数据:
        创建存储过程:

DELIMITER &&     CREATE PROCEDURE delete_data (IN u_id INT(11), OUT effect_number INT(3))     LANGUAGE SQL     BEGIN   DELETE FROM USER WHERE id = u_id;SET effect_number = ROW_COUNT();#ROW_COUNT()用于返回受影响的行数END &&     DELIMITER ;

        调用存储过程:

CALL delete_data(1, @effect_number);  SELECT @effect_number;

        查看存储过程
        存储过程的查看可以通过如下语句实现:SHOW PROCEDURE STATUS  WHERE db='数据库名';或SHOW CREATE PROCEDURE 数据库名.存储过程名;
         删除存储过程: 
        存储过程的删除可以通过如下语句实现:DROP PROCEDURE 存储过程名
         存储过程优点
        1、存储过程增强了SQL语言灵活性。存储过程可以使用控制语句编写,可以完成复杂的判断和较复杂的运算,有很强的灵活性;
        2、减少网络流量,降低了网络负载。存储过程在数据库服务器端创建成功后,只需要调用该存储过程即可,而传统的做法是每次都将大量的SQL语句通过网络发送至数据库服务器端然后再执行;
        3、存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。
        4、系统管理员通过设定某一存储过程的权限实现对相应的数据的访问权限的限制,避免了非授权用户对数据的访问,保证了数据的安全。