mysql 扩展存储过程_MySQL4:存储过程和函数

什么是存储过程

简单说,存储过程就是一条或多条SQL语句的集合,可视为批文件,但是起作用不仅限于批处理。本文主要讲解如何创建存储过程和存储函数以及变量的使用,如何调用、查看、修改、删除存储过程和存储函数等。使用的数据库和表还是之前写JDBC用的数据库和表:

create database school;

use school;

create table student

(

studentId int primary key auto_increment not null,

studentName varchar(10) not null,

studentAge int,

studentPhone varchar(15)

)

insert into student values(null,'Betty', '20', '00000000');

insert into student values(null,'Jerry', '18', '11111111');

insert into student values(null,'Betty', '21', '22222222');

insert into student values(null,'Steve', '27', '33333333');

insert into student values(null,'James', '22', '44444444');

commit;

存储程序可以分为存储过程和函数,MySQL中创建存储过程和函数的语句分别是:CREATE PROCEDURE和CREATE FUNCTION。使用CALL语句来调用存储过程,只能用输出变量返回值。函数可以从语句外调用(即通过引用函数名),也能返回标量值。存储过程也可以调用其他存储过程。

创建存储过程

创建存储过程,需要使用CREATE PROCEDURE语句,语句基本格式如下:

CREATE PROCEDURE sp_name([proc_parameter])

[characteristics ...] routine_body

解释一下:

1、CREATE PROCEDURE为创建存储过程的关键字

2、sp_name为存储过程的名字

3、proc_parameter为指定存储过程的参数列表,列表形式为[IN|OUT|INOUT] param_name type。其中,IN表示输入参数,OUT表示输出参数,INOUT表示既可以输入也可以输出,param_name表示参数名称,type表示参数类型,该类型可以是MySQL数据库中的任意类型

4、characteristics指定存储过程的特性

5、routime_body是SQL代码的内容,可以用BEGIN...END来表示SQL代码的开始和结束

编写存储过程不是简单的事情,可能存储过程中需要复杂的SQL语句,并且要有创建存储过程的权限;但是使用存储过程将简化操作,减少冗余的操作步骤,同时还可以减少操作过程中的事物,提高效率,因此存储过程是非常有用的。下面看两个存储过程,一个查询student表中的所有字段,一个根据student表的Age字段算一个Age的平均值:

CREATE PROCEDURE proc ()

BEGIN

SELECT * FROM student;

END;

CREATE PROCEDURE AvgStudentAge()

BEGIN

SELECT AVG(studentAge) AS avgAge FROM student;

END;

上面都是不带参数的存储过程,下面看一个带参数的存储过程:

DELIMITER //

CREATE PROCEDURE CountStudent(IN sName VARCHAR(10), OUT num INT)

BEGIN

SELECT COUNT(*) INTO num FROM student WHERE studentName = sName;

END //

上述代码的作用是创建一个获取student表记录条数的存储过程,名称为CountStudent,根据传入的学生姓名COUNT(*)后把结果放入参数num中。

注意另外一个细节,上述代码第一行使用了"DELIMITER //",这句语句的作用是把MySQL的结束符设置为"//",因为MySQL默认的语句结束符号为分号";",为了避免与存储过程中SQL语句结束符相冲突,需要使用DELIMITER改变存储过程的结束符,并以"END //"结束存储过程。存过程定义完毕之后再使用"DELIMITER ;"恢复默认结束符。DELIMITER也可以指定其他符号作为结束符。

创建存储函数

创建存储函数需要使用CREATE FUNCATION语句,其基本语法如下:

CREATE FUNCTION func_name([func_parameter]) RETURNS type

[characteristic ...] routine_body

解释一下:

1、CREATE_FUNCTION为用来创建存储函数的关键字

2、func_name表示存储函数的名称

3、func_parameter为存储过程的参数列表,参数列表形式为[IN|OUT|INOUT] param_name type,和存储过程一样

4、RETURNS type表示函数返回数据的类型

5、characteristic表示存储函数的特性,和存储过程一样

举个例子:

CREATE FUNCTION NameByZip() RETURNS CHAR(50)

RETURN (select studentPhone from student where studentName = 'JAMES');

提两点:

1、如果在存储函数中的RETURN语句返回一个类型不同于函数的RETURNS自居指定的类型的值,返回值将被强制为恰当的类型

2、指定参数为IN、OUT或INOUT只对PROCEDURE是合法的(FUNCTION中总是默认为IN参数)。RETURNS子句只能对FUNCTION做指定,对于函数而言这是强制性的,它用来指定函数的返回类型,而且函数体必须包含一个RETURN value语句

变量的使用

变量可以在子程序中声明并使用,这些变量的作用范围是在BEGIN...END程序中,在存储过程中可以使用DECLARE语句定义变量,语法如下:

DECLARE var_name[,varame]... date_type [DEFAULT value]

解释一下:

1、var_name为局部变量的名称

2、DEFAULT value子句给变量提供一个默认值,值除了可以被声明为一个常数之外,还可以被指定为一个表达式。如果没有DEFAULT子句,那么初始值为NULL

定义变量后,为变量赋值可以改变变量的默认值,MySQL使用SET为变量赋值:

SET var_name=expr[, var_name=expr] ...;

举个例子:

DECLARE var1 INT DEFAULT 100;

DECLARE var2, var3, var4 INT;

SET var2 = 10, var3 = 20;

SET var4 = var2 + var3;

当然,我们使用SELECT语句也可以给变量赋值:

DECLARE t_studentName CHAR(20);

DECLARE t_studentAge INT;

SELECT studentName, studentId INTO t_studentName, t_studentAge FROM student where studentName = 'Bruce';DECLARE t_studentName CHAR(20);

DECLARE t_studentAge INT;

游标的使用

查询语句可能返回多条记录,如果数据量非常大,需要在存储过程和存储函数中使用游标来逐条读取查询结果集中的记录。应用程序可以根据需要滚动或浏览器中的程序。

游标必须在处理程序之前被声明,并且变量和条件还必须在声明游标或处理程序之前被声明。MySQL中声明游标的方法为:

DECLARE cursor_name CURSOR FOR select_statement

解释一下:

1、cursor_name表示游标的名称

2、select_statement表示SELECT语句返回的内容,返回一个用于创建游标的结果集

定义了游标,就要打开游标,打开游标的方法为:

OPEN cursor_name{游标名称}

再就是使用游标了,使用游标的方法为:

FETCH cursor_name INTO var_name [, var_name] ... {参数名称}

最后游标使用完了,要关闭:

CLOSE cursor_name{游标名称}

举个例子:

DECLARE t_studentName CHAR(20);

DECLARE t_studentAge INT;

DECLARE cur_student CURSOR FOR SELECT studentName, studentId FROM student where studentName = 'Bruce';

OPEN cur_student;

FETCH cur_student INTO t_studentName, t_studentAge;

...

CLOSE cur_student;

studentName为Bruce的在数据里面不止一条记录,创建游标之后就从student表中查出了studentName和studentId的值。OPEN这个游标,通过FETCH之后遍历每一组studentName和studentAge,并放入申明的变量t_studentName和t_studentAge中,之后想怎么用这两个字段怎么用这两个字段了。注意,游标用完关闭掉。

IF、CASE、LOOP、LEAVE、ITERATE、REPEAT

这六个比较简单,放在一起讲了,简单说下用法,除了第一个IF写个例子以外,别的就不写例子了,可以自己尝试下。

1、IF

IF语句包含多个判断条件,根据判断的结果为TRUE或FALSE执行相应的语句,其格式为:

IF expr_condition THEN statement_list

[ELSEIF expr_condition THEN statement_list]

[ELSE statement_list]

END IF

比如:

IF t_studentName IS NULL

THEN SELECT studentName INTO t_studentName FROM student where studentName = 'Bruce';

ELSE UPDATE studentName set student = NULL where studentName = 'Bruce';

END IF;

2、CASE

case是另外一个进行条件判断的语句,该语句有两种格式,第一种格式如下:

CASE case_expr

WHEN when_value THEN statement_list

[WHEN when_value THEN statement_list] ...

[ELSE statement_list]

END CASE

其中,case_expr参数表示判断的表达式,决定了哪一个WHEN自居会被执行;when_value表示表达式可能的值,如果某个when_value表达式与case_expr表达式结果相同,则执行对应THEN关键字后的statement_list中的语句;statement_list参数表示不同when_value值的执行语句。

CASE语句的第二种格式为:

CASE

WHEN expr_condition THEN statement_list

[WHEN expr_condition THEN statement_list] ...

[ElSE statement_list]

END CASE

只是写法稍微变了一下,参数还是第一种写法的意思

3、LOOP

LOOP循环用来重复执行某些语句,与IF和CASE相比,LOOP只是创建一个循环操作的过程,并不进行条件判断。LOOP内的语句一直被重复执行直到循环被退出,跳出循环过程,使用LEAVE子句。LOOP语句j的基本格式如下:

[loop_label:] LOOP

statement_list

END LOOP

其中loop_label表示LOOP语句的标注名称,该参数可以省略;statement_list参数表示需要循环执行的语句

4、LEAVE

LEAVE语句用来退出任何被标注的流程控制构造,LEAVE语句的基本格式如下:

LEAVE label

5、ITERATE

ITERATE语句将执行顺序转到语句段开头出,语句基本格式如下:

ITERATE label

6、REPEAT

REPEAT语句用来创建一个带有条件判断的循环过程,每次与局执行完毕之后,会对条件表达式进行判断,如果表达式为真,则循环结束,否则重复执行循环中的语句。REPEAT语句的基本格式如下:

[repeat_label:] REPEAT

statement_list

UNTIL expr_condition

END REPEAT

其中,repeat_label为REPEAT语句的标注名称,该参数可以省略;REPEAT语句内的语句或语句群被重复,直至expr_condition为真

调用存储过程和函数

存储过程已经定义好了,接下来无非就是调用。存储过程和函数有很多种调用方法,存储过程必须使用CALL语句调用,并且存储过程和数据库相关,如果要执行其他数据库中的存储过程,需要指定数据库名称,例如CALL dbname.procname。存储函数的调用与MySQL中预定义的函数调用方式相同。

1、调用存储过程

存储过程是通过CALL语句进行调用的,语法如下:

CALL sp_name([parameter[,...]])

举个例子,就调用最前面那个CountStudent的存储过程:

CALL CountStudent('Bruce', @num);

select @num;

运行结果为:

2、调用存储函数

MySQL中调用存储函数的使用方法和MySQL内部函数的使用方法是一样的,无非存储函数是用户自己定义的,内部函数是MySQL开发者定义的。

我们调用一下上面定义的NameByZip那个函数:

select NameByZip();

运行结果为:

可以对照一下,studenName为"James"这一条,对应的studentPhone就是"44444444",符合SELECT出来的结果

查看、删除存储过程和函数

1、查看存储过程和函数的状态

SHOW STATUS可以查看存储过程核函数的状态,其基本语法结构如下:

SHOW {PROCEDURE | FUNCTIOn} STATUS [LIKE 'pattern'

这个语句是一个MySQL的扩展,他返回子程序的特征,如数据库、名字、类型、创建者及创建和修改日期。如果没有指定样式,根据使用的语句,所有存储过程或存储函数的信息都被列出。PROCEDURE和FUNCTIOn分别表示查看存储过程和函数,LIKE语句表示匹配存储过程或函数的名称。

举个例子:

SHOW PROCEDURE STATUS

运行结果为:

后面还有一些字段,截图截不全没办法。查看存储函数也一样,可以自己试试看。

2、查看存储过程和函数的定义

除了SHOW STATUS外,还可以使用SHOW CREATE来查看存储过程的定义,基本格式为:

SHOW CREATE {PROCEDURE | FUNCTION} sp_name

比如:

SHOW CREATE FUNCTION NameByZip

我查看了NameByZip这个函数的定义,结果为:

这个Create Function字段就是创建的存储函数的内容

3、删除存储过程和函数

删除存储过程核函数,可以使用DROP语句,基本语法如下:

DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name

这个语句被用来移除一个存储过程或函数。sp_name为待移除的存储过程或函数的名称。

IF EXISTS子句是一个MySQL的扩展,如果程序或函数不存储,它可以防止错误发生,产生一个用SHOW WARNINGS查看的警告。举个例子:

DROP PROCEDURE CountStudent

DROP FUNCTION NameByZip;

这么简单就可以了。注意这里没有讲修改存储过程和存储函数,因为修改存储过程或者函数只能修改存储过程或者存储函数的特性,不能直接对已有的存储过程或函数进行修改,如果必须要改,只能先DROP在重新编写代码,CREATE一个新的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/505594.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

netcore quartz job用不了services_.NetCore开源集成框架

GitHub地址:https://github.com/zwl568633995/AspNetCoreScaffolding(感兴趣的Fork给个小星星吧~)AspNetCoreScaffolding本框架在.netCore和.netStandard的基础上,集成了多种中间件.NetCore集成框架,即开即用如果对您有…

mysql基准性能测试标准_mysql性能测试与优化——(一),基准测试套件

笔者英语不好,又没人翻译,只好自己动手,希望大家多提意见,我好及时修改,以免误导他人。本文仅供参考,笔者对使用者产生的任何后果,概不负责。 转载请注明出处!正文:The…

python合并数组输出重复项_python进行数组合并的方法

python的数组合并在算法题中用到特别多,这里简单总结一下:假设有a1和a2两个数组:a1[1,2,3]a2[4,5,6]合并方式1. 直接相加#合并后赋值给新数组a3a3 a1 a22. extend#调用此方法,a1会扩展成a1和a2的内容a1.extend(a2)3. 列表表达式…

mysql更新代码_mysql update语句的用法

1. 单表的UPDATE语句:UPDATE [LOW_PRIORITY] [IGNORE] tbl_nameSET col_name1expr1 [, col_name2expr2 ...][WHERE where_definition][ORDER BY ...][LIMIT row_count]2. 多表的UPDATE语句UPDATE [LOW_PRIORITY] [IGNORE] table_referencesSET col_name1expr1…

安装版mysql错误2_【gem安装】mysql2错误

错误信息Gem::Ext::BuildError: ERROR: Failed to build gem native extension./home/jaylin/.rvm/rubies/ruby-2.2.1/bin/ruby -r ./siteconf20150423-6190-1ocfncu.rb extconf.rbchecking for ruby/thread.h... yeschecking for rb_thread_call_without_gvl() in ruby/thread…

linux 父子进程 资源_linux 父子进程 资源_实验4 Linux父子进程同步

实验4 Linux父子进程同步【实验目的】(1)熟悉在c语言源程序中使用linux所提供的系统调用界面的方法。(2)理解同步的概念。(3)使用系统调用wait()和exit(),实现父子进程同步。【实验原理/实验基础知识】一、同步在多道系统中,一个进程相对于另一个进程的…

mysql事件循环执行,Node.js MySQL连接,查询顺序和事件循环

Lets see this exampleconn.query(SET v 1;, (err) > {conn.query(SELECT v;, (err, res) > {// res contains v 1 or 2 ?});});conn.query(SET v 2;, (err) > {conn.query(SELECT v;, (err, res) > {// res contains v 1 or 2 ?});});Does mysql/mysql2 nod…

mysql执行一条语句会加锁吗_一条简单的更新语句,MySQL是如何加锁的?

看如下一条sql语句:# table T (id int, name varchar(20))delete from T where id 10;MySQL在执行的过程中,是如何加锁呢?在看下面这条语句:select * from T where id 10;那这条语句呢?其实这…

mysql命令4类_【Mysql】mysql数据库的一些常用命令

一、启动与退出1、进入MySQL:输入命令:mysql -u root -p直接输入安装时的密码即可。此时的提示符是:mysql>2、退出MySQL:quit或exit3、数据库清屏命令:system clear;二、库操作1、创建数据库命令:create…

u2020 华为_华为MateBook X Pro 2020款评测:全面屏商务旗舰再升级

在今年2月24日举办的华为终端产品与战略线上发布会上,华为正式发布了全新升级的MateBook X Pro 2020款笔记本电脑,并且加入了翡冷翠新色,再一次的奠定了产品高端时尚基调。除此之外,华为MateBook X Pro 2020款还升级了第10代智能英…

java zip文件夹_如何使用java压缩文件夹成为zip包

展开全部在JDK中有一个zip工具类:java.util.zip Provides classes for reading and writing the standard ZIP andGZIP file formats.使用此类可以将文件夹或者多个文件进行打包压缩操作。在使用之前先了解62616964757a686964616fe59b9ee7ad9431333363376462关键…

java -uf_Java如何快速修改Jar包里的文件内容

需求背景:写了一个实时读取日志文件以及监控的小程序,打包成了Jar包可执行文件,通过我们的web主系统上传到各个服务器,然后调用ssh命令执行。每次上传前都要通过解压缩软件修改或者替换里面的配置文件,这样感觉有点麻烦…

java .vm h2_java-H2服务器在调试时挂起

由于正在创建内存数据库,因此启动tcp服务器将无济于事.我建议改为在线程中启动控制台,并在同一段代码(例如,使用jdbc)中打开与此数据库的连接,但不要关闭/释放它.使用此代码段执行此操作:请根据H2文档添加其他选项,例如允许其他人使用(我建议暂时将其保留)org.h2.to…

java 静态变量 new_java中静态对象和普通变量在初始化静态变量的时候有什么区别??高手!!...

下面有一个例子,将语句(6)直接改为一个新的对象后,结果会不同,解释的清楚一些吗??豁出去了,家当10分publicclassStaticVariableTest{privatestaticStaticVariableTestsvtnewS...下面有一个例子,…

java子类怎么编译_java – 无法编译从基类实现抽象方法的子类

编译我已经定义的基类的子类有一个问题,它有一个单独的方法,而每个子类都实现了抽象基类方法,但是javac说他们甚至没有在子类中明确定义它们.DbModel.java(基类)package com.manodestra.db;import java.sql.ResultSet;import java.sql.SQLException;public abstract class DbMo…

java循环遍历类属性_java循环遍历类属性 get 和set值方法

//遍历sqspb类 成员为String类型 属性为空的全部替换为“/”Field[] fields sqspb.getClass().getDeclaredFields();for (int i 0; i < fields.length; i) {// 获取属性的名字String name fields[i].getName();// 将属性的首字符大写&#xff0c;方便构造get&#xff0c;…

java 浏览器 爬虫_java 网络编程-爬虫+模拟浏览器

网络爬虫模拟浏览器(获取有权限网站资源)&#xff1a;获取URL下载资源分析处理public class http {public static void main(String[]args) throws Exception{//https更安全//URL.openStream()打开于URL的连接&#xff0c;并返回一个InputStream用于从连接中读取数据//获取URLU…

java 序列化实例_Java中的序列化与反序列化实例

创建的字节流与平台无关。因此&#xff0c;在一个平台上序列化的对象可以在另一个平台上反序列化。为了使Java对象可序列化&#xff0c;我们实现java.io.Serializable可序列化接口。ObjectOutputStream类包含writeObject()序列化对象的方法。public final voidwriteObject(Obje…

java map for循环遍历_java中Map遍历的四种方式

java中Map遍历的四种方式在java中所有的map都实现了Map接口&#xff0c;因此所有的Map(如HashMap, TreeMap, LinkedHashMap, Hashtable等)都可以用以下的方式去遍历。方法一&#xff1a;在for循环中使用entries实现Map的遍历&#xff1a;/*** 最常见也是大多数情况下用的最多的…

java 代码 _程序员用1.5小时写出的Java代码,让同事瞠目结舌!直呼优秀

1.曾经不止一次在生产中见过类似这样的代码&#xff1a;这有很多变种&#xff0c;例如用 Integer.valueOf(1)、 (Integer)1 之类的&#xff0c;那些细节都不重要。重要的是&#xff1a;凭空用一个 Integer 对象作为锁对象。2.AbstractComponentBuilderTemplateFactory3.HelloWo…