存储过程和函数

  • 简单的说,存储过程就是一条或者多条SQL语句的集合。可以视为批文件,但是其作用不仅仅局限于批处理。本文主要介绍如何创建存储过程和存储函数,以及如何调用、查看、修改、删除存储过程和存储函数等。
创建存储过程和函数

  存储程序分为存储过程和存储函数。Mysql创建存储过程和存储函数的语句分别为CREATE PROCEDURE和CREATE FUNCTION。使用CALL语句来调用存储过程,只能用输出变量返回值。存储函数可以从语句外调用(通过引用函数名),也能返回标量值。存储过程也可以调用其他存储过程。废话少说,如下步入正文。

  • 创建存储过程

  创建存储过程的基本语法格式为:CREATE PROCEDURE sp_name([proc_parameter]) [characteristics] routine_body

  其中CREATE PROCEDURE为创建存储过程的关键字,sp_name为存储过程的名称,pro_parameter为指定存储过程的参数列表,其中参数列表如下:

  1. [IN|OUT|INOUT] param_name type 其中,IN表述输入参数,OUT表示输出参数,INOUT表示即可输入也可输出;param_name表述参数名称;type表示参数类型,该类型可以是MySQL数据库中的任意类型。
  2. characteristics指定存储过程的特性,有以下取值:
    • LANGUAGE SQL:说明routine_body部分是由SQL语句组成的,当前系统支持的语言为SQL,SQL是LANGUAGE特性的唯一值。
    • [NOT] DETERMINISTIC:指明存储过程执行的结果是否正确。DETERMINISTIC表示结果是正确的,每次执行存储过程时,相同的输入会得到相同的输出,NOT 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':注释信息,用来描述存储过程或函数。
  3. routine_body是SQL代码的内容,可以用BEGIN...END来表示SQL代码的开始和结束。

  我们从最简单的存储过程开始说起,如下是不包含任何参数的存储过程,代码为:CREATE PROCEDURE Proc() BEGIN SELECT * FROM tb_score; END; 我们定义了一个名称为Proc的存储过程,该过程是用来查询tb_score(该表接上篇博客,已存在)数据库表中的所有数据。

    

  第一张图是通过执行sql语句查询到tb_score表中的数据。第二张图是创建存储过程,其中第一句DELIMITER //是将MySQL的结束符设置为//,因为MySQL默认的结束符为分号,为了避免与存储过程中SQL语句结束符相冲突,需要DELIMITER改变存储过程的结束符,并以“END //”结束存储过程。第三张图是调用存储过程,在调用存储过程之前先将MySQL结束符恢复为默认的分号(DELIMITER ;)然后通过CALL Proc()调用。

  接下来我们讲解MySQL存储过程中的参数IN、OUT、INOUT,IN作为输入,将输入作为参数传输到存储过程的执行当中去;OUT作为输出,将存储过程的输出通过参数传出来,而INOUT参数可以同时作为输入和输出。

  还是通过存储过程查询tb_score表,不过这次我们要查询课程号为1(cID=1)的所有学生的成绩,存储过程定义为:CREATE PROCEDURE Proc_cID(IN classID INT) BEGIN SELECT * FROM tb_score WHERE cID=classID; END;

  

  如我们需要查询课程号为1的学生的人数和平均成绩,则存储过程定义如下:CREATE PROCEDURE Proc_AVG(IN classID INT,OUT total INT,OUT a_s FLOAT) BEGIN SELECT COUNT(*),AVG(grade) INTO total,a_s FROM tb_score WHERE cID=classID; END;

  • 创建存储函数

  创建存储函数需要使用CREATE FUNCTION语句,基本语法格式为:CREATE FUNCTION func_name([func_parameter]) returns type [characteristic] routine_body CREATE FUNCTION为用来创建存储函数的关键字,func_name表示存储函数的名称,func_parameter为存储过程的参数列表如下:

    • [IN|OUT|INOUT] param_name type 其参数含义同存储过程(PROCEDURE)相同,其默认为IN参数。

RETURNS type语句表示函数返回数据的类型,characteristic指定存储函数的特性,取值与创建存储过程时相同。

  查询某个学生某门课程的成绩函数代码为:CREATE FUNCTION Query_score(classID INT,studentID INT) RETURNS INT RETURN (SELECT grade FROM tb_score WHERE cID=classID AND sID=studentID); 通过SELECT Query_score(1,1)查询1号学生1号课程的成绩。

 

  读者可能会发现存储过程的查询结果可能为多个值,而存储函数的查询结果是某一类型的单值。而且存储过程在调用时用CALL而存储函数是SELECT。那么存储过程和函数具体的区别又是什么呢?

  1. 存储过程的功能更加复杂,而函数的功能针对性更强;
  2. 存储过程可以返回参数(通过OUT|INOUT),而函数只能返回单一值或者表对象;
  3. 存储过程作为一个独立的部分来执行,而函数可以作为查询语句的一部分来调用,由于函数可以返回一个表对象,因此它可以在查询语句中位于FROM关键字之后;
  4. 存储过程是通过关键字CALL来调用,作为一个独立的执行部分。而存储函数则可作为SELECT语句的一部分调用,嵌入到SQL语句中;
  5. 当存储过程和函数被执行的时候,SQLManager会到procedure cache中去取相应的查询语句,如果在procedure cache里没有相应的查询语句,SQLManager就会对存储过程和函数进行编译。
  • 变量的使用

  变量可以在子程序中声明并使用,作用范围是在BEGIN...END程序中,如下将主要介绍如何定义变量和为变量赋值。

  1. 定义变量。语法格式为:DECLARE var_name[,var_name]...data_type[DEFAULT value]; var_name为局部变量名称,DEFAULT value给变量提供一个默认值。值除了可以被声明为一个常数之外,还可以被指定为一个表达式。如果缺少DEFAULT子句,初始值为NULL。
  2. 为变量赋值。MySQL中使用SET语句为变量赋值,语法格式为:SET var_name=expr[,var_name=expr]...
  • 流程控制的使用

  流程控制与用来根据条件控制语句的执行。MySQL中的用来构造控制流程的语句有:IF语句、CASE语句、LOOP语句、LEAVE语句、ITERATE语句、REPEAT语句和WHILE语句。各语句介绍如下:

  1. IF语句。包含多个条件判断,根据判断的结果为TRUE或FALSE执行相应的语句,语法格式为 IF expr_condition THEN statement_list ESLEIF expr_condition THEN statement_list ESLE statement_list END IF 如下我们定义一个学生成绩等级评定函数,将学生成绩以参数的形式传输函数,输出学生成绩等级A(90~100)、B(75~90)、C(60~75)、D(60以下)。代码编写中需要注意,IF中如果有多个限制条件,限制条件间用AND连接,DECLARE的变量声明必须在BEGIN内,以及字符串之间拼接用CONCAT。该功能代码如下图所示:
  2. CASE语句。另外一个进行条件判断的语句,该语句有2种语句格式。
    1. 第一种格式为:CASE case_expr WHEN value THEN statement_list [WHEN value THEN statement_list] [ELSE statement_list] END CASE 其中case_expr参数表示条件判断的表达式,决定哪个WHEN子句会被执行,value表示表达式可能的值,如果case_expr等于某个value,则执行相应value后的statement_list。
    2. 第二种格式为:CASE WHEN expr_condition THEN statement_list [WHEN expr_condition THEN statement_list] [ELSE statement_list] END CASE 其中expr_condition参数表示条件判断语句,该格式下,WHEN语句将被逐个执行,直到某个expr_condition表达式为真,则这行对应THEN关键字后面的statement_list语句。如果没有匹配,ELSE子句里的语句被执行。
  3. LOOP语句。循环语句用来重复执行某些语句,与IF和CASE相比,LOOP只是创建一个循环操作的过程,并不进行条件判断。LOOP内的语句一直重复执行直到循环被退出。跳出循环过程使用LEAVE子句,LOOP语句基本格式为:[label] LOOP statement_list END LOOP[label] label表示LOOP语句的标注名称,该参数可以省略,statement_list表示需要执行的语句。
  4. LEAVE语句。从LOOP语句的例子中可知LEAVE语句用来退出任何被标注的流程控制构造,LEAVE语句基本格式为:LEAVE label

  5. ITERATE语句。将执行顺序转到语句段开头处,语句基本格式为:ITERATE lable ITERATE只可以出现在LOOP、REPEAT和WHILE语句内。ITERATE的意思为再次循环,label参数表示循环的标志。ITERATE语句必须跟在循环标志前面。例子中p1=0,如果p1的值小于10时,重复执行p1加1操作;p1大于等于10并且小于20时,打印消息'p1 is between 10 and 20';p1大于20时,退出循环。
  6. REPEAT语句。创建一个带条件判断的循环过程,每次语句执行完毕后,会对条件表达式进行判断,表达式为真循环结束,否则重复执行循环中的语句。语句基本格式:[label]:REPEAT statement_list UNTIL expr_condition END REPEAT [label]

  7. WHILE语句。WHILE语句创建一个带条件判断的循环过程,与REPEAT不同,WHILE在执行语句时先对指定的表达式进行判断,为真则执行循环内的语句,否则退出循环。语句基本格式:[label] WHILE expr_condition DO statement_list END WHILE [label]
查看存储过程和函数

  MySQL中,用户可以使用SHOW STATUS语句或SHOW CREATE语句来查看存储过程和函数,也可以直接从系统的information_schema数据库中查询。本节将通过实例来介绍这3种方法。

  • SHOW STATUS语句查看存储过程和函数的状态,其基本语法为:SHOW{PROCEDURE|FUNCTION} STATUS [LIKE 'pattern'] 这个语句返回子程序的特征,如数据库、名字、类型、创建者及创建和修改日期。如果没有指定样式,根据使用的语句,所有存储程序或存储函数的信息都被列出。PROCEDURE和FUNCTION分别表示查看存储过程和函数,LIKE语句表示匹配存储过程或函数的名称。
  • SHOW CREATE查看存储过程和函数语句格式为:SHOW CREATE {PROCEDURE|FUNCTION} sp_name 它返回一个可以来重新创建已命名子程序的确切字符串。PROCEDURE和FUNCTION分别表示查看存储过程和函数,同样也可是使用LIKE匹配。

  • 从information_schema.Routines表中查看存储过程和函数的信息。MySQL中存储过程和函数的信息存储在information_schema数据库的Routines表中。通过查询该表的记录查询存储过程和函数的信息。基本语法格式为:SELECT * FROM information_schema.Routines WHERE ROUTINE_NAME='sp_name' 其中ROUTINE_NAME字段存储的是存储过程和函数的名称,sp_name参数表述存储过程或函数的名称。

修改存储过程和函数

  使用ALTER语句可以修改存储过程或函数的特性,本节将介绍如何通过ALTER语句修改存储过程和函数。语法格式为:ALTER {PROCEDURE|FUNCTION} sp_name [characteristic ...] 其中,sp_name参数表示存储过程或函数的名称,characteristic参数指定存储函数的特性,可能的取值有:

  1. CONTAINS SQL表示子程序包含SQL语句,但是不包含读或写数据的语句;
  2. NO SQL表示子程序中不包含SQL语句;
  3. READES SQL DATA表示子程序中包含读数据的语句;
  4. MODIFIES SQL DATA表示子程序中包含写数据的语句;
  5. SQL SECURITY{DEFINER|INVOKER}指明谁有权限来执行;
  6. DEFINER表示只有定义着自己才能够执行;
  7. INVOKER表示调用者可以执行;
  8. COMMENT 'string'表示注释信息。

  修改存储过程使用ALTER PROCEDURE语句,修改存储函数使用ALTER FUNCTION语句。

 

删除存储过程

  删除存储过程和函数可以使用DROP语句,语法格式为:DROP {PROCEDURE|FUNCTION} [IF EXISTS] sp_name 这个语句被用来移除一个存储过程或函数,sp_name为要移除的存储过程或函数的名称。IF EXISTS子句是一个MySQL的扩展,如果存储过程或函数不存在,以防发生错误,产生一个用SHOW WARNINGS查看的警告。

  最后再说几点值得大家注意的吧:

  1. 目前MySQL不支持对已存在的存储过程代码进行修改,如果必须修改,则先使用DROP语句删除该存储过程,再重新创建新的存储过程;
  2. 存储过程中包含用户定义的SQL语句集合,也可是使用CALL语句调用存储过程,但不能使用DROP删除其他存储过程;
  3. 在定义存储过程参数列表时,应注意把参数名与数据库表中的字段名区别开,否则会报错。
  4. 如果存储过程中需要传入中文参数,这时需要在定义存储过程的时候,在参数后加上character set gbk,不然调用存储过程使用中文参数会出错。如CREATE PROCEDURE userInfo(IN u_name VARCHAR(50) character set gbk, OUT u_age INT)。

SQL中的存储过程和函数的更多相关文章

  1. SQL Server中的CLR编程——用.NET为SQL Server编写存储过程和函数

    原文:SQL Server中的CLR编程--用.NET为SQL Server编写存储过程和函数 很早就知道可以用.NET为SQL Server2005及以上版本编写存储过程.触发器和存储过程的,不过之 ...

  2. 用sql语句导出oracle中的存储过程和函数

    用sql语句导出oracle中的存储过程和函数: SET echo off ; SET heading off ; SET feedback off ; SPOOL 'C:/PRC.SQL' repl ...

  3. 剑指Offer——常用SQL语句、存储过程和函数

    剑指Offer--常用SQL语句.存储过程和函数 常用SQL语句 1.在MySQL数据库建立多对多的数据表关系 2.授权.取消授权 grant.revoke grant select, insert, ...

  4. MySQL中的存储过程和函数

    存储过程和函数 简单的说,存储过程就是一条或者多条SQL语句的集合.可以视为批文件,但是其作用不仅仅局限于批处理.本文主要介绍如何创建存储过程和存储函数,以及如何调用.查看.修改.删除存储过程和存储函 ...

  5. Oracle学习2 视图 索引 sql编程 游标 存储过程 存储函数 触发器

    ---视图 ---视图的概念:视图就是提供一个查询的窗口,来操作数据库中的数据,不存储数据,数据在表中. ---一个由查询语句定义的虚拟表. ---查询语句创建表 create table emp a ...

  6. SQL中Round(),Floor(),Ceiling()函数的浅析

    项目中的一个功能模块上用到了标量值函数,函数中又有ceiling()函数的用法,自己找了一些资料,对SQL中这几个函数做一个简单的记录,方便自己学习.有不足之处欢迎拍砖补充 1.round()函数遵循 ...

  7. C#调用SQL中的存储过程中有output参数,存储过程执行过程中返回信息

      C#调用SQL中的存储过程中有output参数,类型是字符型的时候一定要指定参数的长度.不然获取到的结果总是只有第一字符.本人就是由于这个原因,折腾了很久.在此记录一下,供大家以后参考! 例如: ...

  8. Qt调用Server SQL中的存储过程

    Server SQL中的存储过程如下: CREATE procedure PINSERTPC @pcnum int, @pcname varchar(50), @pctype int, @ipaddr ...

  9. 在sql中使用了 hashbytes 函数

    在做项目的时候,在sql中使用了hashbytes函数,运用md5算法去加密一密码.代码如下 DECLARE @psw nvarchar(20) SET @psw = 'admin' SELECT h ...

随机推荐

  1. limesurvey设置短调查问卷url

    If you want to use fancy URLs and so not have /index.php in every URL please edit /application/confi ...

  2. EF 实体字段设置主键和自增

    [Key] //主键 [DatabaseGenerated(DatabaseGeneratedOption.Identity)] //设置自增 public int id { get; set; } ...

  3. java设计模式笔记(1)-适配器模式

    适配器的定义 适配器就是一个接口转换器,它可以是一个独立的硬件接口设备,允许硬件或电子接口与其它硬件或电子接口相连,也可以是信息接口.比如:电源适配器.三角架基座转接部件.USB与串口的转接设备等. ...

  4. Button背景图片有拉伸

    1.将图片做成9.png2.用TextView 3.将minHeight, minWidth设为0 4.http://blog.csdn.net/oathevil/article/details/23 ...

  5. Ubuntu切换默认语言

    不得不说,从Ubuntu到Debian,又到CentOS 7,我胡汉三又回来了... 然后又装了个中文版的Ubuntu16.04LTS,不得不说,Ubuntu对中文的支持真的很好 不过,还是不太习惯, ...

  6. [NOI2011]阿狸的打字机(好题!!!!)

    2785: [NOI2011]阿狸的打字机 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 7  Solved: 3[Submit][Status][We ...

  7. apue- chapter 1 UNIX基础知识

    1.C++实现ls命令 #include<dirent.h> #include<stdlib.h> #include<iostream> #include &quo ...

  8. Vue 响应式总结

    有些时候,不得不想添加.修改数组和对象的值,但是直接添加.修改后getter.setter又失去了. 由于 JavaScript 的限制, Vue 不能检测以下变动的数组: 当你利用索引直接设置一个项 ...

  9. Mysql死锁问题解决方式 & 聚簇索引、隔离级别等知识

    参考了这篇文章:http://www.cnblogs.com/LBSer/p/5183300.html  <mysql死锁问题分析> 写的不错. 如果Mysql死锁,会报出: 1.1 死锁 ...

  10. max-width

    #main { max-width: 600px; margin: 0 auto; } <div id="main"> Using max-width instead ...