数据库存储过程讲解与实例视频_mysql存储过程实例详解

数据库 (2) 2024-08-06 11:23

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说
数据库存储过程讲解与实例视频_mysql存储过程实例详解,希望能够帮助你!!!。

目录

1 存储过程简介

2 存储过程使用

2.1 创建存储过程

2.2 in,out以及inout


1 存储过程简介

 SQL语句需要先编译然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。

    存储过程是可编程的函数,在数据库中创建并保存,可以由SQL语句和控制结构组成。当想要在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的。数据库中的存储过程可以看做是对编程中面向对象方法的模拟,它允许控制数据的访问方式。

优点

  • 存储过程可封装,并隐藏复杂的商业逻辑。
  • 存储过程可以回传值,并可以接受参数。
  • 存储过程无法使用 SELECT 指令来运行,因为它是子程序,与查看表,数据表或用户定义函数不同。
  • 存储过程可以用在数据检验,强制实行商业逻辑等。

缺点

  • 存储过程,往往定制化于特定的数据库上,因为支持的编程语言不同。当切换到其他厂商的数据库系统时,需要重写原有的存储过程。
  • 存储过程的性能调校与撰写,受限于各种数据库系统。

2 存储过程使用

存储过程的一些基本语法:

--------------创建存储过程----------------- CREATE PROC [ EDURE ] procedure_name [ ; number ] [ { @parameter data_type } [ VARYING ] [ = default ] [ OUTPUT ] ] [ ,...n ] [ WITH { RECOMPILE | ENCRYPTION | RECOMPILE , ENCRYPTION } ] [ FOR REPLICATION ] AS sql_statement [ ...n ] --------------调用存储过程----------------- EXECUTE Procedure_name '' --存储过程如果有参数,后面加参数格式为:@参数名=value,也可直接为参数值value --------------删除存储过程----------------- drop procedure procedure_name --在存储过程中能调用另外一个存储过程,而不能删除另外一个存储过程

创建存储过程的参数:
1.procedure_name :存储过程的名称,在前面加#为局部临时存储过程,加##为全局临时存储过程。

2.; number:是可选的整数,用来对同名的过程分组,以便用一条 DROP PROCEDURE 语句即可将同组的过程一起除去。例如,名为 orders 的应用程序使用的过程可以命名为 orderproc;1、orderproc;2 等。DROP PROCEDURE orderproc 语句将除去整个组。如果名称中包含定界标识符,则数字不应包含在标识符中,只应在 procedure_name 前后使用适当的定界符。 

3.@parameter: 存储过程的参数。可以有一个或多个。用户必须在执行过程时提供每个所声明参数的值(除非定义了该参数的默认值)。存储过程最多可以有 2.100 个参数。 
使用 @ 符号作为第一个字符来指定参数名称。参数名称必须符合标识符的规则。每个过程的参数仅用于该过程本身;相同的参数名称可以用在其它过程中。默认情况下,参数只能代替常量,而不能用于代替表名、列名或其它数据库对象的名称。有关更多信息,请参见 EXECUTE。 

4.data_type:参数的数据类型。所有数据类型(包括 text、ntext 和 image)均可以用作存储过程的参数。不过,cursor 数据类型只能用于 OUTPUT 参数。如果指定的数据类型为 cursor,也必须同时指定 VARYING 和 OUTPUT 关键字。有关 SQL Server 提供的数据类型及其语法的更多信息,请参见数据类型。 
说明 对于可以是 cursor 数据类型的输出参数,没有最大数目的限制。 

5.VARYING: 指定作为输出参数支持的结果集(由存储过程动态构造,内容可以变化)。仅适用于游标参数。 

6.default: 参数的默认值。如果定义了默认值,不必指定该参数的值即可执行过程。默认值必须是常量或 NULL。如果过程将对该参数使用 LIKE 关键字,那么默认值中可以包含通配符(%、_、[] 和 [^])。

7.OUTPUT :表明参数是返回参数。该选项的值可以返回给 EXEC[UTE]。使用 OUTPUT 参数可将信息返回给调用过程。Text、ntext 和 image 参数可用作 OUTPUT 参数。使用 OUTPUT 关键字的输出参数可以是游标占位符。 

8.RECOMPILE: 表明 SQL Server 不会缓存该过程的计划,该过程将在运行时重新编译。在使用非典型值或临时值而不希望覆盖缓存在内存中的执行计划时,请使用 RECOMPILE 选项。

9.ENCRYPTION: 表示 SQL Server 加密 syscomments 表中包含 CREATE PROCEDURE 语句文本的条目。使用 ENCRYPTION 可防止将过程作为 SQL Server 复制的一部分发布。 说明 在升级过程中,SQL Server 利用存储在 syscomments 中的加密注释来重新创建加密过程。 

10.FOR REPLICATION :指定不能在订阅服务器上执行为复制创建的存储过程。.使用 FOR REPLICATION 选项创建的存储过程可用作存储过程筛选,且只能在复制过程中执行。本选项不能和 WITH RECOMPILE 选项一起使用。 

11.AS :指定过程要执行的操作。

12.sql_statement :过程中要包含的任意数目和类型的 Transact-SQL 语句。但有一些限制。

2.1 创建存储过程

UserAccount
UserID UserName PassWord RegisterTime RegisterIP
12 6                    6                    2012-12-31 6
18 5                    5                    2013-01-01 5
19 1                    1                    2013-01-01 1
20 2                    2                    2013-01-01 2
21 3                    3                    2013-01-01 3
22 4                    4                    2013-01-01 4
23 5                    5                    2013-01-01 5
25 7                    7                    2013-01-01 7
26 8                    8                    2013-01-01 8
NULL NULL NULL NULL NULL

针对上面的表,我使用存储过程对它做一些操作:

1. 只返回单一记录集的存储过程 

-------------创建名为GetUserAccount的存储过程---------------- create Procedure GetUserAccount as select * from UserAccount go -------------执行上面的存储过程---------------- exec GetUserAccount

 结果:相当于运行 select * from UserAccount 这行代码,结果为整个表的数据。

2.没有输入输出的存储过程 

-------------创建名为GetUserAccount的存储过程---------------- create Procedure inUserAccount as insert into UserAccount (UserName,[PassWord],RegisterTime,RegisterIP) values(9,9,'2013-01-02',9) go -------------执行上面的存储过程---------------- exec inUserAccount

结果:相当于运行 insert into UserAccount (UserName,[PassWord],RegisterTime,RegisterIP) values(9,9,'2013-01-02',9) 这行代码。

3.有返回值的存储过程 

-------------创建名为GetUserAccount的存储过程---------------- create Procedure inUserAccountRe as insert into UserAccount (UserName,[PassWord],RegisterTime,RegisterIP) values(10,10,'2013-01-02',10) return @@rowcount go -------------执行上面的存储过程---------------- exec inUserAccountRe

 解释:这里的@@rowcount为执行存储过程影响的行数,执行的结果是不仅插入了一条数据,还返回了一个值即 return value =1  ,这个可以在程序中获取,稍后在c#调用存储过程中会有说到。

4.有输入参数和输出参数的存储过程 

-------------创建名为GetUserAccount的存储过程---------------- create Procedure GetUserAccountRe @UserName nchar(20), @UserID int output as if(@UserName>5) select @UserID=COUNT(*) from UserAccount where UserID>25 else set @UserID=1000 go -------------执行上面的存储过程---------------- exec GetUserAccountRe '7',null

解释:@UserName为输入参数,@UserID为输出参数。 运行结果为@userID为COOUT(*)即 =1。

5. 同时具有返回值、输入参数、输出参数的存储过程 

-------------创建名为GetUserAccount的存储过程---------------- create Procedure GetUserAccountRe1 @UserName nchar(20), @UserID int output as if(@UserName>5) select @UserID=COUNT(*) from UserAccount where UserID>25 else set @UserID=1000 return @@rowcount go -------------执行上面的存储过程---------------- exec GetUserAccountRe1 '7',null

结果:@userID为COOUT(*)即 =1,Retun Value=1。

6.同时返回参数和记录集的存储过程 

-------------创建名为GetUserAccount的存储过程---------------- create Procedure GetUserAccountRe2 @UserName nchar(20), @UserID int output as if(@UserName>5) select @UserID=COUNT(*) from UserAccount where UserID>25 else set @UserID=1000 select * from UserAccount return @@rowcount go -------------执行上面的存储过程---------------- exec GetUserAccountRe2 '7',null

结果:返回执行 select * from UserAccount 这句代码的结果集,同时@userID为COOUT(*)即 =1,Retun Value=9。 

7.返回多个记录集的存储过程 

-------------创建名为GetUserAccount的存储过程---------------- create Procedure GetUserAccountRe3 as select * from UserAccount select * from UserAccount where UserID>5 go -------------执行上面的存储过程---------------- exec GetUserAccountRe3

结果:返回两个结果集,一个为 select * from UserAccount,另一个为 select * from UserAccount where UserID>5 。

2.2 in,out以及inout

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

    IN,OUT,INOUT
    格式为:Create procedure|function([[IN |OUT |INOUT ] 参数名 数据类形...])

    IN 输入参数
        表示该参数的值必须在调用存储过程时指定,在存储过程中修改该参数的值不能被返回,为默认值

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

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

1.参数in的使用(代表输入,意思说你的参数要传到存过过程的过程里面去)

//为了避免存储过程中分号(";")结束语句,我们使用分隔符告诉mysql解释器,该段命令是否已经结束了。

/** 案例功能:求1-n的和 */ delimiter $ create procedure p1(in n int) begin declare total int default 0; declare num int default 0; while num < n do set num:=num+1; set total:=total+num; end while; select total; end$ call p1(10)$

创建并执行完存储过程,运行结果如下:

数据库存储过程讲解与实例视频_mysql存储过程实例详解_https://bianchenghao6.com/blog_数据库_第1张

2.参数out的使用(代表往外输出)

//这里还要注意一点的就是我们的输出参数一定要设置相应类型的初始,否则不管你怎么计算得出的结果都为NULL值

/** 案例功能:求1-n的和 */ create procedure p2(in n int,out total int) begin declare num int default 0; set total:=0; while num < n do set num:=num+1; set total:=total+num; end while; end$

注意:对于第一个输入参数我们可以理解,但是第二个输出参数我们到底应该怎么输?

这里我们需要对第二个参数定义一个变量名(更形象点就是你输入一个输入类型的参数n,由输出参数total往外发射输出我们只需要定义一个变量名来接收这个输出值即可)

call p2(100,@sum)$//这里的@sum就是我定义用来接收处处total的值

select @sum$

创建并执行完存储过程(查询定义的变量值),运行结果如下:

数据库存储过程讲解与实例视频_mysql存储过程实例详解_https://bianchenghao6.com/blog_数据库_第2张

总结in、out区别:

in:表示输入一个值,你需要一个值,我给你一个值

out:你往外输出一个值,你输出的那个值我就拿一个变量来接收你给我输出的那个值

3.参数inout的使用(既能输入一个值又能传出来一个值)

/** 功能:传一个年龄,自动让年龄增长10岁 */ create procedure p3(inout age int) begin set age:=age+10; end$

注意:调用的时候,我这里需要和大家声明一下,inout型的参数值既是输入类型又是输出类型,你给它一个值,值不是变量,不是变量那out的时候它怎么赋给这个值是不是?

因此我们需要先设置一个变量并初始化这个值,调用的时候直接传这个变量即可。

set @currentAge=8$

call p3(@currentAge)$

select @currentAge$

创建并执行完存储过程,运行结果如下:

数据库存储过程讲解与实例视频_mysql存储过程实例详解_https://bianchenghao6.com/blog_数据库_第3张

使用参数的存储过程(备注:decimal(8,2)意思就是总共有8位,小数点后留两位)

create procedure procedureName(      out min decimal(8,2),      out avg decimal(8,2),      out max decimal(8,2)  )  BEGIN      select MIN(price) INTO min from order;      select AVG(price) into avg from order;      select MAX(price) into max from order;  END;  

此过程接受三个参数, 分别用于获取订单表的最小、平均、最大价格。每个参数必须具有指定的类

型,这里使用十进制值(decimal(8,2)), 关键字OUT指出相应的参数用来从存储过程传出

一个值(返回给调用者)

MySQL支持IN(传递给存储过程)、OUT(从存储过程传出,如这里所用)和INOUT(对存储过程传入和传出)类型的参数。存储过程的代码位于BEGIN和END语句内,如前所见,它们是一系列SELECT语句,用来检索值,然后保存到相应的变量(通过指定INTO关键字)

为调用此修改过的存储过程,必须指定3个变量名,如下所示:(所有MySQL变量都必须以@开始。)

 

-- 由于过程指定三个参数, 故调用必须要参数匹配  call procedureName(@min, @avg, @max);  

该调用并没有任何输出, 只是把调用的结果赋给了调用时传入的变量(@min, @avg, @max)。然后即可调用显示该变量的值。

select @min, @avg, @max; 

结果如下

@min @avg @max
42.00 601.00 2222.00

使用in参数, 输入一个用户id, 返回该用户所有订单的总价格。

create procedure getTotalById (      in userId int,      out total decimal(8,2)  )  BEGIN      select SUM(r.price) from order r      where r.u_id = userId      into total;  END;  

调用存储过程

 

call getTotalById(1, @total);  select @total;  

结果将返回该用户所有订单的合计价格。

复杂一点的过程, 根据用户id获取该用户的所有订单价格, 并动态的选择是否加税。代码设计如下

 

create procedure getTotalByUser2(      in userId int,      in flag boolean, -- 是否加税标记      out total decimal(8,2)  )  begin      DECLARE tmptotal DECIMAL(8,2);      DECLARE taxrate int DEFAULT 6;-- 默认的加税的利率            select SUM(r.price) from order r      where r.u_id = userId      into tmptotal;            if flag then          select tmptotal + (tmptotal/1000*taxrate) into tmptotal;      end if;            select tmptotal into total;  END;  

该过程传入三个参数, 用户id, 是否加税以及返回的总价格,在过程内部, 定义两个局部变量tmptotal和taxrate,把查询出来的结果赋给临时变量, 在判断是否加税。最后把局部变量的值赋给输出参数。

 

call getTotalByUser2(1, false, @total); -- 不加税  call getTotalByUser2(1, true, @total);  -- 加税  select @total; 

 

 

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

发表回复