s端子是什么-win8双系统安装

mysqlprocedure
2023年4月4日发(作者:media player 12)

MySQL存储过程

1.存储过程简介

我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,

而存储过程(StoredProcedure)是一组为了完成特定功能的SQL语句集,经编译

后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程

带有参数)来调用执行它。

一个存储过程是一个可编程的函数,它在数据库中创建并保存。它可以有SQL

语句和一些特殊的控制结构组成。当希望在不同的应用程序或平台上执行相同的

函数,或者封装特定功能时,存储过程是非常有用的。数据库中的存储过程可以

看做是对编程中面向对象方法的模拟。它允许控制数据的访问方式。

存储过程通常有以下优点:

(1).存储过程增强了SQL语言的功能和灵活性。存储过程可以用流控制语句编写,

有很强的灵活性,可以完成复杂的判断和较复杂的运算。

(2).存储过程允许标准组件是编程。存储过程被创建后,可以在程序中被多次调

用,而不必重新编写该存储过程的SQL语句。而且数据库专业人员可以随时对

存储过程进行修改,对应用程序源代码毫无影响。

(3).存储过程能实现较快的执行速度。如果某一操作包含大量的Transaction-SQL

代码或分别被多次执行,那么存储过程要比批处理的执行速度快很多。因为存储

过程是预编译的。在首次运行一个存储过程时查询,优化器对其进行分析优化,

并且给出最终被存储在系统表中的执行计划。而批处理的Transaction-SQL语句

在每次运行时都要进行编译和优化,速度相对要慢一些。

(4).存储过程能过减少网络流量。针对同一个数据库对象的操作(如查询、修改),

如果这一操作所涉及的Transaction-SQL语句被组织程存储过程,那么当在客户

计算机上调用该存储过程时,网络中传送的只是该调用语句,从而大大增加了网

络流量并降低了网络负载。

(5).存储过程可被作为一种安全机制来充分利用。系统管理员通过执行某一存储

过程的权限进行限制,能够实现对相应的数据的访问权限的限制,避免了非授权

用户对数据的访问,保证了数据的安全。

2.关于MySQL的存储过程

存储过程是数据库存储的一个重要的功能,但是MySQL在5.0以前并不支持存

储过程,这使得MySQL在应用上大打折扣。好在MySQL5.0终于开始已经支持

存储过程,这样即可以大大提高数据库的处理速度,同时也可以提高数据库编程

的灵活性。

存储过程的创建

(1).格式

MySQL存储过程创建的格式:

CREATEPROCEDURE过程名([过程参数[,...]])procedure

[特性...]过程体

这里先举个例子:

mysql>DELIMITER//

mysql>CREATEPROCEDUREproc1(OUTsint)

->BEGIN

->SELECTCOUNT(*)INTOsFROMuser;

->END

->//

mysql>DELIMITER;

注:

(1)这里需要注意的是DELIMITER//和DELIMITER;两句,DELIMITER是分

割符的意思,因为MySQL默认以";"为分隔符,如果我们没有声明分割符,那么

编译器会把存储过程当成SQL语句进行处理,则存储过程的编译过程会报错,

所以要事先用DELIMITER关键字申明当前段分隔符,这样MySQL才会将";"当

做存储过程中的代码,不会执行这些代码,用完了之后要把分隔符还原。

(2)存储过程根据需要可能会有输入、输出、输入输出参数,这里有一个输出

参数s,类型是int型,如果有多个参数用","分割开。

(3)过程体的开始与结束使用BEGIN与END进行标识。

这样,我们的一个MySQL存储过程就完成了,是不是很容易呢?看不懂也没关

系,接下来,我们详细的讲解。

(2).声明分割符

delimiter分隔符

delimiter//

其实,关于声明分割符,上面的注解已经写得很清楚,不需要多说,只是稍微要

注意一点的是:如果是用MySQL的Administrator管理工具时,可以直接创建,

不再需要声明。

(3).参数

MySQL存储过程的参数用在存储过程的定义,共有三种参数类

型,IN,OUT,INOUT,形式如:

CREATEPROCEDURE([[IN|OUT|INOUT]参数名数据类形...])

CREATEPROCEDURE(in)……》输入参数参数值由外向procedure内传即外面给

个值,里面获得,但仅单向传递值,即内部改变传不到外部。

CREATEPROCEDURE(out)……》输出参数外部定的参数值不能传到内部,但内

部参数可传单外部。

IN输入参数:表示该参数的值必须在调用存储过程时指定,在存储过程中修改该

参数的值不能被返回,为默认值

OUT输出参数:该值可在存储过程内部被改变,并可返回

INOUT输入输出参数:调用时指定,并且可被改变和返回

Ⅰ.IN参数例子

创建:

mysql>DELIMITER//

mysql>CREATEPROCEDUREdemo_in_parameter(INp_inint)

->BEGIN

->SELECTp_in;/*查询输入参数*/

->SETp_in=2;/*修改*/

->SELECTp_in;/*查看修改后的值*/

->END;

->//

mysql>DELIMITER;

执行结果:

mysql>SET@p_in=1;

mysql>CALLdemo_in_parameter(@p_in);

+------+

|p_in|

+------+

|1|

+------+

+------+

|p_in|

+------+

|2|

+------+

mysql>SELECT@p_in;

+-------+

|@p_in|

+-------+

|1|

+-------+

以上可以看出,p_in虽然在存储过程中被修改,但并不影响@p_id的值

Ⅱ.OUT参数例子

创建:

mysql>DELIMITER//

mysql>CREATEPROCEDUREdemo_out_parameter(OUTp_outint)

->BEGIN

->SELECTp_out;/*查看输出参数*/

->SETp_out=2;/*修改参数值*/

->SELECTp_out;/*看看有否变化*/

->END;

->//

mysql>DELIMITER;

执行结果:

mysql>SET@p_out=1;

mysql>CALLsp_demo_out_parameter(@p_out);

+-------+

|p_out|

+-------+

|NULL|

+-------+

/*未被定义,返回NULL*/

+-------+

|p_out|

+-------+

|2|

+-------+

mysql>SELECT@p_out;

+-------+

|p_out|

+-------+

|2|

+-------+

Ⅲ.INOUT参数例子

创建:

mysql>DELIMITER//

mysql>CREATEPROCEDUREdemo_inout_parameter(INOUTp_inoutint)

->BEGIN

->SELECTp_inout;

->SETp_inout=2;

->SELECTp_inout;

->END;

->//

mysql>DELIMITER;

执行结果:

mysql>SET@p_inout=1;

mysql>CALLdemo_inout_parameter(@p_inout);

+---------+

|p_inout|

+---------+

|1|

+---------+

+---------+

|p_inout|

+---------+

|2|

+---------+

mysql>SELECT@p_inout;

+----------+

|@p_inout|

+----------+

|2|

+----------+

(4).变量

Ⅰ.变量定义

DECLAREvariable_name[,variable_name...]datatype[DEFAULTvalue];

其中,datatype为MySQL的数据类型,如:int,float,date,varchar(length)

例如:

unsigned无符号

整型的每一种都有无符号(unsigned)和有符号(signed)两种类型(float

和double总是带符号的),在默认情况下声明的整型变量都是有符号的类型(char

有点特别),如果需声明无符号类型的话就需要在类型前加上unsigned。无符号

版本和有符号版本的区别就是无符号类型能保存2倍于有符号类型的数据,比如

16位系统中一个int能存储的数据的范围为-32768~32767,而unsigned能存储的

数据范围则是0~65535。由于在计算机中,整数是以补码形式存放的。根据最高位

的不同,如果是1,有符号数的话就是负数;如果是无符号数,则都解释为正数。

同时在相同位数的情况下,所能表达的整数范围变大。另外,unsigned若省略后

一个关键字,大多数编译器都会认为是unsignedint。

在sql语句中的意义

sql语句中,创建一个数据表时

ceatetableuser{

user_idintunsigned...

...

}

当中的unsigned表示,数据项user_id恒为正整数。

declare变量名称变量的数据类型约束条件;

DECLAREl_intintunsigneddefault4000000;

DECLAREl_numericnumber(8,2)DEFAULT9.95;

DECLAREl_datedateDEFAULT'1999-12-31';

DECLAREl_datetimedatetimeDEFAULT'1999-12-3123:59:59';

El_varcharvarchar(255)DEFAULT'Thiswillnotbepadded';

Ⅱ.变量赋值

SET变量名=表达式值[,variable_name=expression...]

selectcol_name[,....]intovar_name[,....]fromtable条件

实例:动态查询f_name,f_price给ruitname,和fruitprice赋值

selectf_name,f_priceintofruitname,fruitpricefromfruitswheref_id=’a1’;

.注释

单行注释--

多行注释/*……*/

MySQL存储过程可使用两种风格的注释

双模杠:--

该风格一般用于单行注释

c风格:/*注释内容*/一般用于多行注释

流程控制使用

1:if语句

例10.14】IF语句的示例,代码如下:

if()

{

功能代码;

}else

{

功能代码;

}

条件语句:

If语句:

if(条件)then

执行M

endif

If-then-else语句:

If(条件)then

执行M

Else

执行N

Endif

Case语句:

case变量when1then执行1when2then执行2(类似于java中switch变量case1:

执行1;case2:执行2)

循环语句:

Loop语句:标签:loop循环体判断语句thenleave标签

Repeat语句:[标签]repeat循环体until判断语句endrepeat[标签]

while条件do循环体;endwhile;

IFvalISNULL

THENSELECT'valisNULL';

ELSESELECT'valisnotNULL';

ENDIF;

Ⅰ.if-then-else语句

mysql>DELIMITER//

mysql>CREATEPROCEDUREproc2(INparameterint)

->begin

->declare(声明)varint;

->setvar=parameter+1;

->ifvar=0then

->insertintotvalues(17);

->endif;

->ifparameter=0then

->updatetsets1=s1+1;

->else

->updatetsets1=s1+2;

->endif;

->end;

->//

mysql>DELIMITER;

【例10.15】使用CASE流程控制语句判断val值等于1、等于2,或者两者都不

等,语句如下:

delimiter//

createprocedureprocase()

begin

declarevalint;

setval=1;

caseval

when1thenselect'valis1';

when2thenselect'valis2';

endcase;

end

//

case变量

when条件1then功能1;

when条件2then功能2;

endcase;

CASEval

WHEN1THENSELECT'valis1';

WHEN2THENSELECT'valis2';

ELSESELECT'valisnot1or2';

ENDCASE;

mysql>DELIMITER//

mysql>CREATEPROCEDUREproc3(inparameterint)

->begin

->declarevarint;

->setvar=parameter+1;

->casevar

->when0then

->insertintotvalues(17);

->when1then

->insertintotvalues(18);

->else

->insertintotvalues(19);

->endcase;

->end;

->//

mysql>DELIMITER;

【例10.16】使用CASE流程控制语句判断val是否为空、小于0、大于0或者等

于0,或者两者都不等,语句如下:

CASE

WHENvalISNULLTHENSELECT'valisNULL';

WHENval<0THENSELECT'valislessthan0';

WHENval>0THENSELECT'valisgreaterthan0';

ELSESELECT'valis0';

ENDCASE;

loop循环

【例10.17】使用LOOP语句的进行循环操作,id值小于等于10之前,将重复

执行循环过程,代码如下:

DECLAREidINTDEFAULT0;

add_loop:LOOP

SETid=id+1;

IFid>10THENLEAVEadd_loop;

ENDIF;

ENDLOOPadd_loop;

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

leavelabel

iterate语句将执行顺序转到语句开头处

语法格式

iteratelabel

iterate只可以出现在loop,repeatwhile语句中

iterate的意思是再次循环环

label参数表示循环的标志。iterate语句必须跟在循环标志前面。

mysql>DELIMITER//

mysql>CREATEPROCEDUREproc6()

->begin

->declarevint;

->setv=0;

->LOOP_LABLE:loop

->insertintotvalues(v);

->setv=v+1;

->ifv>=5then

->leaveLOOP_LABLE;

->endif;

->endloop;

->end;

->//

mysql>DELIMITER;

【例10.18】ITERATE语句示例,代码如下:

CREATEPROCEDUREdoiterate()

BEGIN

DECLAREp1INTDEFAULT0;

my_loop:LOOP

SETp1=p1+1;

IFp1<10THENITERATEmy_loop;

ELSEIFp1>20THENLEAVEmy_loop;

ENDIF;

SELECT'p1isbetween10and20';

ENDLOOPmy_loop;

END

mysql>DELIMITER//

mysql>CREATEPROCEDUREproc10()

->begin

->declarevint;

->setv=0;

->LOOP_LABLE:loop

->ifv=3then

->setv=v+1;

->ITERATELOOP_LABLE;

->endif;

->insertintotvalues(v);

->setv=v+1;

->ifv>=5then

->leaveLOOP_LABLE;

->endif;

->endloop;

->end;

->//

mysql>DELIMITER;

repeat语句创建一个带条件判断的循环过程,每次语句执行完毕之后,会对条件

表达式进行判断,如果表达式为真,则循环环结束,否则重复执行循环中语句。

repeat语法的基本格式如下:

[repeat_label:]repeat

statement_list

utilexpr_condition

endrepeat[repeat:label]

【例10.19】REPEAT语句示例,id值小于等于10之前,将重复执行循环过程,

代码如下:

repeat

。。。。。。功能代码,循环体

until条件

endrepeat;

DECLAREidINTDEFAULT0;

REPEAT

SETid=id+1;

UNTILid>=10

ENDREPEAT;

mysql>DELIMITER//

mysql>CREATEPROCEDUREproc5()

->begin

->declarevint;

->setv=0;

->repeat

->insertintotvalues(v);

->setv=v+1;

->untilv>=5

->endrepeat;

->end;

->//

mysql>DELIMITER;

【例10.20】WHILE语句示例,id值小于等于10之前,将重复执行循环过程,

代码如下:

while条件

do

循环体;

endwhile;

delimiter//

createprocedureprocwhile()

DECLAREiINTDEFAULT0;

WHILEi<10

DO

SETi=i+1;

selectnow();

ENDWHILE;

end

//

Ⅰ.while····endwhile:

mysql>DELIMITER//

mysql>CREATEPROCEDUREproc4()

->begin

->declarevarint;

->setvar=0;

->whilevar<6do

->insertintotvalues(var);

->setvar=var+1;

->endwhile;

->end;

->//

mysql>DELIMITER

光标的使用

查询语句可能返回多条记录,如果数据量非常大,需要在存储过程和存储函数中

使用光标来逐条读取查询结果集中的记录。应用程序可以根据需要滚动或浏览其

中的数据,本节将介绍如何声明,打开,使用关闭光标。

声明光标:

Declarecursor_nameCURSORFORselect_statement

例10.10】声明名称为cursor_fruit的光标,代码如下:

DECLAREcursor_fruitCURSORFOR(粗略的)SELECTf_name,f_priceFROM

fruits;

打开光标:

Opencursor_name;

【例10.11】打开名称为cursor_fruit的光标,代码如下:

OPENcursor_fruit;

使用光标:

FETCH光标名称intovar_name,var_price;

语法格式fetchcursor_nameintovar_name,var_price

【例10.12】使用名称为cursor_fruit的光标。将查询出来的数据存入fruit_name

和fruit_price这两个变量中,代码如下:

FETCHcursor_fruitINTOfruit_name,fruit_price;

关闭光标

【例10.13】关闭名称为cursor_fruit的光标,代码如下:

CLOSEcursor_fruit;

定义条件和处理程序

特定条件需要特定处理。这些条件可以联系到错误,以及子程序中一般流程控制。

定义条件事先定义程序执行过程中遇到的问题,处理程序定义了在遇到这些问题

是应当采取的处理方式,别且保证存储过程或函数在遇到警告或者错误时能继续

执行。这样可以增强存储程序处理问题的能力,避免程序异常停止工作。

定义条件

Declarecondition_nameconditionfor[condition_type]

[condition_type]:

sqlstate[value]sqlstate_value|mysql_error_code

sqlstate_value和mysql_error_code都可以表示MySQL的错误,sqlstate_value为

长度为5的字符串类型的错误代码,mysql_error_code

为类型错误代码:例如error1142(42000)中,sqlstate_value的值是:

42000,my_error_code的值是1142

【例10.7】定义"ERROR1148(42000)"错误,名称为command_not_allowed。可以

用两种不同的方法来定义,代码如下:

//方法一:使用sqlstate_value

DECLAREcommand_not_allowedCONDITIONFORSQLSTATE'42000';

//方法二:使用mysql_error_code

DECLAREcommand_not_allowedCONDITIONFOR1148

【例10.8】定义处理程序的几种方式,代码如下:

//方法一:捕获sqlstate_value

DECLARECONTINUEHANDLERFORSQLSTATE'42S02'SET@info='NO_SUCH_

TABLE';

//方法二:捕获mysql_error_code

DECLARECONTINUEHANDLERFOR1146SET@info='NO_SUCH_TABLE';

//方法三:先定义条件,然后调用

DECLAREno_such_tableCONDITIONFOR1146;

DECLARECONTINUEHANDLERFORNO_SUCH_TABLESET@info='NO_SUCH

_TABLE';

//方法四:使用SQLWARNING

DECLAREEXITHANDLERFORSQLWARNINGSET@info='ERROR';

//方法五:使用NOTFOUND

DECLAREEXITHANDLERFORNOTFOUNDSET@info='NO_SUCH_TABLE';

//方法六:使用SQLEXCEPTION

DECLAREEXITHANDLERFORSQLEXCEPTIONSET@info='ERROR';

【例10.9】定义条件和处理程序,具体执行的过程如下:

CREATETABLEtest.t

(s1int,primarykey(s1));

DELIMITER//

CREATEPROCEDUREhandlerdemo()

BEGIN

DECLARECONTINUEHANDLERFORSQLSTATE'23000'SET@x2=1;

SET@x=1;

S(1);

SET@x=2;

S(1);

SET@x=3;

END;

//

DELIMITER;

CALLhandlerdemo();/*调用存储过程*/

SELECT@x;/*查看调用过程结果*/

存储函数:创建存储函数使用createfunction(存储函数参数列表)

returns返回的数据类型

return(selects_namefromsupplierswheres_call=’48075’);

调用此存储函数

select存储函数名称();

delimiter//

createfunctioncount()

returnschar(50)

return(selectcount(*)fromfruitswheres_id=103);

//

调用存储函数

selectcount();

MySQL存储过程的调用

用call和你过程名以及一个括号,括号里面根据需要,加入参数,参数包括输入

参数、输出参数、输入输出参数。具体的调用方法可以参看上面的例子。

callproccedure_name([param]);

存储过程的查询

我们像知道一个数据库下面有那些表,我们一般采用showtables;进行查看。那么

我们要查看某个数据库下面的存储过程,是否也可以采用呢?答案是,我们可以

查看某个数据库下面的存储过程,但是另一种方式。

我们可以用

Showprocedurestatus;

模糊查询某个数据库的存储过程

Showprocedurestatuslike‘p%’;

进行查询。

如果我们想知道,某个存储过程的详细,那我们又该怎么做呢?是不是也可以像

操作表一样用describe表名进行查看呢?

答案是:我们可以查看存储过程的详细,但是需要用另一种方法:

SHOWCREATEPROCEDURE数据库.存储过程名;

例如:查询数据库test1中proIF存储过程的详细信息

;

就可以查看当前存储过程的详细。

存储过程的修改

ALTERPROCEDURE

更改用CREATEPROCEDURE建立的预先指定的存储过程,其不会影响相关存

储过程或存储功能。

存储过程的删除

删除一个存储过程比较简单,和删除表一样:

DROPPROCEDURE

例如删除:test中的proIF

dropprocedureproIF;

从MySQL的表格中删除一个或多个存储过程。

存储过程的实例:

创建一个名称为sch的数据表,表结构如表10.1所示将表10.2中的数据插入到

sch表中

idint(10)主键非空唯一,

namevarchar(50)非空,

glassvarchar(50)非空

sch表内容

idnameglass

1xiaomingglass1

2xiaojunglass2

步骤1:创建一个sch表,并且向sch表中插入表格中的数据

CREATETABLEsch(idINT,nameVARCHAR(50),glassVARCHAR(50));

INSERTINTOschVALUE(1,’xiaoming’,’1班’),(1,’xiaojun’,’2班’);

步骤2:创建一个存储函数用来统计表sch中记录数

/*创建存储函数*/

DELIMITER//

CREATEFUNCTIONcount_sch()

RETURNSINT

RETURN(SELECTCOUNT(*)FROMsch);

//

/*调用存储函数*/

SELECTcount_sch()//

DELIMITER;

步骤3:创建一个存储过程,通过调用存储函数的方法来获取表sch中记录数和

sch表中id的和。

/*创建存储过程*/

DELIMITER//

CREATEPROCEDUREadd_id(outcountINT)

BEGIN

DECLAREitmpINT;

DECLAREcur_idCURSORFORSELECTidFROMsch;

DECLAREEXITHANDLERFORNOTFOUNDCLOSEcur_id;

SELECTcount_sch()INTOcount;

SET@sum=0;

OPENcur_id;

REPEAT

FETCHcur_idINTOitmp;

IFitmp<10

THENSET@sum=@sum+itmp;

ENDIF;

UNTIL0ENDREPEAT;

CLOSEcur_id;

END//

/*查看存储过程调用后的结果*/

SELECT@a,@sum//

DELIMITER;

更多推荐

mysqlprocedure