存储过程简单来说,就是为以后的使用而保存的一条或多条MySQL语句的集合。可将其视为批文件,虽然它们的作用不仅限于批处理。
使用存储过程有3个主要的好处,即简单、安全、高性能。显然,它们都很重要。不过,在将SQL代码转换为存储过程前,也必须知道它的一些缺陷。
MySQL称存储过程的执行为调用,因此MySQL执行存储过程的语句为CALL。 CALL接受存储过程的名字以及需要传递给它的任意参数。请看以下例子:
一个返回产品平均价格的存储过程。以下是其代码:
CREATE PROCEDURE productpricing()
BEGIN
SELECT Avg(prod_price) AS priceaverage FROM products;
END;
注意:这里会报错,因为默认的MySQL语句分隔符为;
解决办法是临时更改命令行实用程序的语句分隔符,如下所示:
最后,为恢复为原来的语句分隔符,可使用DELIMITER ;
。
在MySQL处理这段代码时,它创建一个新的存储过程productpricing。没有返回数据,因为这段代码并未调用存储过程,这里只是为以后使用而创建它。
mysql> CALL productpricing();
+--------------+
| priceaverage |
+--------------+
| 16.133571 |
+--------------+
为删除刚创建的存储过程,可使用以下语句:
DROP PROCEDURE productpricing;
仅当存在时删除 如果指定的过程不存在,则DROP PROCEDURE将产生一个错误。当过程存在想删除它时(如果过程不存在也不产生错误)可使用DROP PROCEDURE IF EXISTS。
productpricing只是一个简单的存储过程,它简单地显示SELECT语句的结果。一般,存储过程并不显示结果,而是把结果返回给你指定的变量。
变量(variable) 内存中一个特定的位置,用来临时存储数据。
以下是productpricing的修改版本(如果不先删除此存储过程,则不能再次创建它):
CREATE PROCEDURE productpricing(
out pl DECIMAL(8, 2),
out ph DECIMAL(8, 2),
out pa DECIMAL(8, 2)
)
BEGIN
SELECT Min(prod_price)
INTO pl
FROM products;
SELECT Max(prod_price)
INTO ph
FROM products;
SELECT Avg(prod_price)
INTO pa
FROM products;
END;
为调用此修改过的存储过程,必须指定3个变量名,如下所示:
CALL productpricing(@pricelow, @pricehigh, @priceaverage);
变量名 所有MySQL变量都必须以@开始。
为了显示检索出的产品平均价格,可如下进行:
SELECT @priceaverage;
SELECT @pricehigh, @pricelow, @priceaverage;
下面是另外一个例子,这次使用IN和OUT参数。 ordertotal接受订单号并返回该订单的合计:
CREATE PROCEDURE ordertotal(
IN onumber INT,
OUT ototal DECIMAL(8,2)
)
BEGIN
SELECT Sum(item_price*quantity)
FROM orderitems
WHERE order_num = onumber
INTO ototal;
END;
为调用这个新存储过程,可使用以下语句:
CALL ordertotal(20005, @total);
为了显示此合计,可如下进行:
SELECT @total;
为了得到另一个订单的合计显示,需要再次调用存储过程,然后重新显示变量:
CALL ordertotal(20009, @total);
SELECT @total;
只有在存储过程内包含业务规则和智能处理时,它们的威力才真正显现出来。
考虑这个场景。你需要获得与以前一样的订单合计,但需要对合计增加营业税,不过只针对某些顾客(或许是你所在州中那些顾客)。那么,你需要做下面几件事情:
存储过程的完整工作如下:
-- Name: ordertotal
-- Parameters: onumber = order number
-- taxable = 0 if not taxable, 1 if taxable
-- ototal = order total variable
CREATE PROCEDURE ordertotal(
IN onumber INT,
IN taxable BOOLEAN,
OUT ototal DECIMAL(8,2)
) COMMENT 'Obtain order total, optionally adding tax'
BEGIN
-- Declare variable for total
DECLARE total DECIMAL(8,2);
-- Declare tax percentage
DECLARE taxrate INT DEFAULT 6;
-- Get the order total
SELECT Sum(item_price*quantity)
FROM orderitems
WHERE order_num = onumber
INTO total;
-- Is this taxable?
IF taxable THEN
-- Yes, so add taxrate to the total
SELECT total+(total/100*taxrate) INTO total;
END IF;
-- And finally, save to out variable
SELECT total INTO ototal;
END;
这显然是一个更高级,功能更强的存储过程。为试验它,请用以下两条语句:
CALL ordertotal(20005, 0, @total);
SELECT @total;
CALL ordertotal(20005, 1, @total);
SELECT @total;
为显示用来创建一个存储过程的CREATE语句,使用SHOW CREATEPROCEDURE语句:
SHOW CREATE PROCEDURE ordertotal;
为了获得包括何时、由谁创建等详细信息的存储过程列表, 使用SHOW PROCEDURE STATUS。
限制过程状态结果 SHOW PROCEDURE STATUS列出所有存储过程。为限制其输出,可使用LIKE指定一个过滤模式,例如:SHOW PROCEDURE STATUS LIKE ‘ordertotal’;