SQL必知必会—使用存储过程

《SQL必知必会》读书笔记

1.存储过程

存储过程,是SQL语句和流程控制语句的集合。存储过程是一组为了完成特定功能的SQL语句集,经过第一处编译后存储在数据库,再次调用不需要再次编译。用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。

存储过程中包含逻辑控制语句和数据操纵语句,它可以接受参数,输出参数,返回单个或多个数据集以及返回值。

2.为什么要使用存储过程

使用存储过程的理由:

  • 通过把处理封装在一个易用的单元中,可以简化复杂的操作。
  • 由于不要求反复建立一系列处理步骤,因而保证了数据的一致性。如果所有开发人员和应用程序都使用同一存储过程,则所使用的代码都是相同的。(这一点的延伸就是防止错误。需要执行的步骤越多,出错的可能性就越大。防止错误保证了数据的一致性。)
  • 简化对变动的管理。如果表名、列名或业务逻辑(或别的内容)有变化,那么只需更改存储过程的代码。使用它的人员甚至不需要知道这些变化。(这一点的延伸就是安全性。通过存储过程限制对基础数据的访问,减少了数据讹传[无意识的或别的原因所导致的数据讹传]的机会)。
  • 因为存储过程通常以编译过的形式存储,所以DBMS处理命令的工作较少,提高了性能。
  • 存在一些只能用在单个请求中的SQL元素和特性,存储过程可以使用它们来编写功能更强更灵活的代码。

换句话说,使用存储过程由三个主要的好处,即简单、安全、高性能。

存储过程的缺陷:

  • 不同DBMS中的存储过程语句有所不同。
  • 一般来说,编写存储过程比编写基本SQL语句更复杂,需要更高的技能,更丰富的经验。

3.执行存储过程

EXECUTE接受存储过程名和需要传递给它的任何参数。

EXECUTE AddNewProduct(
        'JTS01',
        'Stuffed Eiffel Tower',
        6.49,
        'Plush stuffed toy with the text La Tour Eiffel in red white and blue'
);

这里执行一个名为AddNewProduct的存储过程,将一个新产品添加到Products表中。AddNewProduct由四个参数,分别是:供应商ID(Vendors表的主键)、产品名、价格和描述。这4个参数匹配存储过程中4个预期变量(定义存储过程自身的组成部分)。

我们注意到,在Products表中还有另一个需要值得列prod_id列,它是这个表的主键。为什么这个值不作为属性传递给存储过程?要保证恰当地生成此ID,最好是使生成此ID的过程自动化(而不是依赖于最终用户的输入)。

以上就是存储过程执行的基本形式。对于具体的DBMS,可能包括以下的执行选择:

  • 参数可选,具有不提供参数时的默认值;
  • 不按次序给出参数,以“参数=值”的方式给出参数值。
  • 输出参数,允许存储过程在正执行的应用程序中更新所用的参数。
  • 用SELECT语句检索数据。
  • 返回代码,允许存储过程返回一个值到正在执行的应用程序。

4.创建存储过程

下面例子,是对邮件发送清单中具有邮件地址的顾客进行计数。

CREATE PRODUCT MailingListCount(
    ListCount OUT INTEGER
)
IS
v_rows INTEGER;
BEGIN 
    SELECT COUNT(*) INTO v_rows
    FROM Customers
    WHERE NOT cust_email IS NULL;
    ListCount := v_rows;
END;

这个存储过程有一个名为ListCount的参数。此参数从存储过程返回一个值而不是传递一个值给存储过程。关键字OUT用来指示这种行为。Oracle支持IN(传递值给存储过程)、OUT(从存储过程·返回值,如这里)、INOUT(既传递值给存储过程也从存储过程传回值)类型的参数。存储过程的代码括在BEGIN和END语句中,这里执行一条简单的SELECT语句,它检索具有邮件地址的顾客。然后用检索处的行数设置ListCount(要传递的输出参数)。

调用过程可以像下面这样:

var ReturnValue NUMBER
EXEC MailingListCount(:ReturnValue);
SELECT ReturnValue;

这段代码声明了一个变量来保存存储过程返回的任何值,然后执行存储过程,再使用SELECT语句显示返回的值。

下面是另一个例子,这次在Orders表中插入一个新订单。此程序仅适用于SQL Server,但它说明了存储过程的某些用途和技术:

CREATE PROCEDURE NewOrder @cust_id CHAR(10)
AS
-- Declare variable for older number
DECLARE @order_num INTRGER
-- Get current highest order number
SELECT @order_num = MAX(order_num)
-- Determine next order number
SELECT @order_num = @order_num + 1
-- Insert new order
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(@order_num,GETDATE(),@cust_id)
-- Return order number
RETURN @order_num;

此存储过程在Orders表中创建一个新订单。它只有一个参数,即下订单顾客的ID。订单号和订单日期这两列在存储过程中自动生成。代码首先声明一个局部变量来存储订单号。接着,检索当前最大订单号(使用MAX()函数)并增加1(使用SELECT语句)。然后用INSERT语句插入由新生成的订单号、当前系统日期(用GETDATE()函数检索)和传递的顾客ID组成的订单。最后,用RETUN @order_num返回订单号(处理订单物品要它)。请注意,此代码加了注释,在编写存储过程时应该多家注释。

附注:
参考文章:https://blog.csdn.net/tojohnonly/article/details/70738629

-- 创建应该存储过程
create procedure GetUsers()
begin
    select * from user;
end;

-- 调用存储过程
call Getusers();

-- 输出存储过程
drop procedure if exists Getusers;

带参数的存储过程:

例1:

create procedure GetScores(
    out minScore decimal(8,2),
    out avgScore decimal(8,2),
    out maxScore decimal(8,2)
)

begin
    select min(score) into minScore from user;
    select avg(score) into avgScore from user;
    select max(score) into maxScore from user;
end;

调用此存储过程,必须指定3个变量(所有MySql变量都必须以@开始),如下所示:

call GetUsers(@minScore,@avgScore,@maxScore);

该调用并没有任何输出,只是把调用的结果赋给了调用时传入的变量@minScore,@avgScore,@maxScore,然后即可调用显示该变量的值:

select @minScore,@avgScore,@maxScore;

例2:

使用IN参数,输入一个用户id,返回该用户的名字:

create procedure GetNameById(
    in userID int,
    out userName varchar(200)
)

begin
    select name from user
    where id = userID
    into userName;
end;

调用存储过程:

call GetNameByID(1,@userName);
select @userName;

猜你喜欢

转载自blog.csdn.net/u014465934/article/details/80041563