什么是存储过程和函数
  存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句的集合,调用存储过程和函数可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的。
  存储过程和函数的区别在于函数必须有返回值,而存储过程没有,存储过程的参数可以使用IN、OUT、INOUT类型,而函数的参数只能是IN类型的。如果有函数从其他类型的数据库迁移到MySQL,那么可能因此需要将函数改造成存储过程。
  为什么使用存储过程和函数
  在完成一个逻辑操作时,有时会执行多条SQL语句,此外这些SQL语句的执行顺序也不是固定的,它会根据条件的变化而变化。在执行过程中,这些需要根据前面SQL语句的执行结果有选择的执行后面的SQL语句。为了解决该问题,MySQL软件提供了数据库对象存储过程和函数。
  存储过程和函数的优点
  <1> 存储过程和函数允许标准组件式编程提高了SQL语句的重用性、共享性和可移植性。
  <2> 存储过程和函数能够实现较快的执行速度,减少网络流量。
  <3> 存储过程和函数可以被作为一种安全机制来利用
  存储过程和函数的缺点
  <1> 存储过程和函数的编写比单句SQL语句复杂,需要用户具有更高的技能和更丰富的经验。
  <2> 在编写存储过程和函数时,需要创建这些数据库对象的权限。
  存储过程和函数的相关操作 创建、修改存储过程或者函数
  创建、修改存储过程或者函数的语法如下:
  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(支持MySQL中的所有数据类型)
  调用语法:
  CALL sp_name([parameter[,…]])
  MySQL的存储过程或者函数中允许包含DDL语句,也允许在存储过程中执行提交(Commit,即确认之前的修改)或者回滚(Rollback,即放弃之前的修改),但是存储过程或者函数中不允许执行LOAD DATA INFILE语句。此外,存储过程和函数中可以调用其他的过程或者函数。
  示例1:在员工姓名模糊查询时,可能需要匹配不同的查询条件,有时需要查询名字中带有“李”的,有时需要查询以“梅”结尾的,此时可以创建一个存储过程根据不同的传入参数,返回不同的结果:
  mysql>DELIMITER $$
  ->CREATE PROCEDURE emp_in_hire(IN emp_name_reg VARCHAR(10),OUT emp_count INT)
  ->READS SQL DATA
  ->BEGIN
  ->SELECT id FROM emp WHERE ename REGEXP emp_name_reg;
  ->SELECT FOUND_ROWS() INTO emp_count;
  ->END $$
  mysql>DELIMITER ;
  mysql>CALL emp_in_hire ('^李',@emp_count);
  +----+
  | id |
  +----+
  | 2 |
  +----+
  1 row in set (0.00 sec)
  Query OK, 1 row affected (0.00 sec)
  mysql>SELECT @emp_count;
  +------------+
  | @emp_count |
  +------------+
  | 1 |
  +------------+
  1 row in set (0.00 sec)
  示例中可以根据传入的第一个参数指定员工姓名匹配的正则表达式,第二个参数用来接收存储过程的输出参数。达到了一段SQL多次使用的目的,不用在业务逻辑中多次编写SQL语句。
  但是在进行上面的例子中可以这样尝试一下,将IN类型的参数emp_name_reg 的类型定义为VARCHAR,也是不指定长度,这样的情况在MySQL5.6版本中会创建失败。但是INT类型的参数不需要指定长度。使用VARCHAR指定传入参数的类型时,没有指定长度,创建时总是提示检查语法。
  还有需要注意的是,在参数命名时,存储过程的参数名不要跟字段名一样。将会导致参数的值将不会是传入的值,而是变成每条记录中对应字段的值。这样的后果,是非常严重的。比如执行单个删除操作:
  DELIMITER $$
  CREATE PROCEDURE delete_one_emp(IN ename VARCHAR(10))
  BEGIN
  DELETE FROM EMP WHERE ename=ename;
  END $$
  调用上面的存储过程时,传入’李四’,意图是删除姓名为李四的员工信息,但是执行后发现,整张表的数据被清空了,即便是字段名是大写,参数名是小写也会如此,因为MySQL对大小写不敏感。
  示例2:创建函数将指定员工的工资增加指定的值,然后返回工资的大值。
  DELIMITER $$
  CREATE FUNCTION add_salary(raise_count int(5),e_name_reg varchar(10))
  RETURNS int(10)
  COMMENT ’涨工资’
  BEGIN
  UPDATE EMP SET SALARY = SALARY+raise_count WHERE ENAME RLIKE e_name_reg;
  RETURN (SELECT max(SALARY) FROM EMP);
  END $$
  DELIMITER;
  SELECT add_salary(5000,'^李');
  存储过程和函数的CREATE语法不支持使用CREATEOR REPLACE对存储过程和函数进行修改,如果需要对已有的存储过程或者函数进行修改需要执行ALTER语法。
  在存储过程和函数的创建语法中有characteristic特性,下面对该特性值的部分进行说明。
  <1>LANGUAGE SQL:说明下面过程的BODY是使用SQL语言编写,这条是系统默认的,为以后除SQL外的其他语言支持的存储过程而准备。
  <2>[NOT]DETERMINISTIC:DETERMINISTIC确定的,即每次输入一样输出也一样的程序,NOT DETERMINISTIC非确定的,默认的是非确定的。当前,这个特征值还没有被优化程序使用。
  <3>{CONTAINS SQL|NOT SQL|READS SQL DATA|MODIFIES SQL DATA}:这些特征值提供子程序使用数据的内在信息,这些特征值目前只是提供给服务器,并没有根据这些特征值来约束过程实际使用数据的情况。CATAINS SQL表示子程序不包含读或写的语句。NOT SQL表示子程序不包含SQL语句。READS SQL DATA表示子程序包含读数据的语句,但是不包含写数据的语句。MODIFIES SQL DATA表示子程序包含写数据的语句。如果这些特征值没有明确给定,默认使用的值CONTAINS SQL。
  <4>SQL SECURITY{DEFINER|INVOKER}:可以用来指定子程序该用创建子程序者的许可来执行,还是使用调用者的许可来执行。默认是DEFINER。
  <5>COMMENT :存储过程或者函数的注释信息。