MySQL存储过程编程时一个复杂的主题,我们将在本章中为你提供完成基本任务的内容,其中包括:
1、怎样创建存储过程
2、存储过程怎样进行输入输出
3、怎样和数据库交互
4、怎样用MySQL存储编程语言创建过程,函数和触发器
第一个存储过程实例:
1
2
3
4
5
6
7
|
delimiter $$
drop
procedure
if exists HelloWorld$$
create
procedure
HelloWorld()
begin
select
"Hello World"
;
end
$$
变量
|
本地变量可以用declare语句进行声明。变量名称必须遵循MySQL的列明规则,并且可以使MySQL内建的任何数据类型。你可以用default字句给变量一个初始值,并且可以用SET语句给变量赋一个新值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
delimiter $$
drop
procedure
if exists variable_demo$$
begin
declare
my_integer
int
;
declare
my_big_integer
bigint
;
declare
my_currency
numeric
(8, 2);
declare
my_pi
float
default
3.1415926;
declare
my_text text;
declare
my_dob
date
default
'1960-06-21'
;
declare
my_varchar
varchar
(30)
default
"Hello World!"
;
set
my_integer = 20;
set
my_big_integer = power(my_integer, 3);
end
$$
delimiter;
|
参数
参数可以使我们的存储程序更为灵活,更为实用。参数包括IN(只读模式), INOUT(可读写模式)和OUT(只写模式)。IN模式作为缺省的参数模式。
IN:任何对于该参数的修改都不会返回给调用它的程序
OUT:这个模式意味着存储过程可以对参数赋值(修改参数的值),并且这个被修改的值会被返回给它的调用程序
INOUT:这个模式意味着存储过程即可读取传入的参数,而且任何对于该参数的修改对于它的调用程序而言都是可见的
对于存储函数而言,只能使用IN模式
1
2
3
4
5
6
7
8
|
delimiter $$
drop
procedure
if exists my_sqrt$$
create
procedure
my_sqrt(input_number
int
,
out
out_number
float
)
begin
set
out_number = SQRT(input_number);
end
$$
delimiter;
|
创建和执行使用OUT参数的存储过程
1
2
3
4
5
|
call my_sqrt(12, @out_value) $$
select
@out_value $$
条件执行
|
通过购买量的多少来计算出贴现率的存储程序,购买量超过$500可以返回20%,购买量超过$100可以返回10%。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
delimiter $$
drop
procedure
if exists discounted_price$$
create
procedure
discounted_price(normal_price
NUMERIC
(8, 2),
out
discount_price NUMBERIC(8, 2))
begin
if (normal_price > 500)
then
set
discount_price = normal_price*.8;
else
if (normal_price > 100)
then
set
discount_price = normal_price*.9;
else
set
discount_price = normal_price;
end
if;
end
$$
delimiter;
循环
|
MySQL存储程序语言提供了三种类型的循环
使用LOOP和END LOOP字句的简单循环
当循环条件为真时继续执行的循环,使用WHILE和END WHILE字句
循环直至条件为真,使用REPEAT和UNTIL字句
在这三种循环中,你都可以使用LEAVE字句来终止循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
DELIMITER $$
DROP
PROCEDURE
IF EXISTS simple_loop$$
CREATE
PROCEDURE
simple_loop()
BEGIN
DECLARE
counter
INT
DEFAULT
0;
my_simple_loop: LOOP
SET
counter = counter 1;
IF counter = 10
THEN
LEAVE my_simple_loop;
END
IF;
END
IF;
END
LOOP my_simple_loop;
select
"I can count to 10"
;
END
$$ DELIMITER;
错误处理
|
1、如果你认为内嵌的SQL语句会返回空记录,或者你想用游标捕获SELECT语句所返回的记录,那么一个NO FOUND 错误处理可以防止存储过程过早的被终止
2、如果你认为SQL语句可能返回错误(比如违背约束条件),你可以创建一个错误处理来阻止程序终止。这个处理将代替你的默认错误处理并继续程序的执行。
和数据库交互
大多数存储过程包含了各种和数据库表的交互,它们包括四种主要的交互:
1、将一个SQL语句所返回的单个记录放入本地变量中。
2、创建一个“游标”来迭代SQL语句所返回的结果集
3、执行一个SQL语句,将执行后的结果集返回给它的调用程序
4、内嵌一个不反悔结果集的SQL语句,如INSERT,UPDATE, DELETE等
对本地变量使用SELECT INTO
当需要在单个记录数据中获取查询信息,你就可以使用SELECT INTO 语法(无论是使用单个记录,多个记录的混合数据,还是多个表连接)。在这种情况下,你可以再SELECT语句中跟随一个INTO子句,告诉MySQL得到的查询数据返回给谁
1
|
DELIMITER $$
DROP
PROCEDURE
IF EXISTS customer_sales $$
CREATE
PROCEDURE
customer_sales(int_customer_id
INT
) READS SQL DATA
BEGIN
DECLARE
total_sales
NUMERIC
(8, 2);
SELECT
SUM
(sale_value)
INTO
total_sales
FROM
sales
WHERE
customer_id = in_customer_id;
SELECT
CONCAT(
'Total sales for '
, in_customer_id,
'is'
,
'total_sales'
);
END
; $$
|
使用游标
SELECT INTO 定义了单记录查询,但是很多应用程序要求查询多记录数据,你可以使用MySQL中的游标来实现这一切,游标允许你将一个或更多的SQL结果集放进存储程序变量中,通常用来执行结果集中各个单记录的处理。
1
|
DELIMITER $$
DROP
PROCEDURE
cursor_example()
READ
SQL DATA
BEGIN
DECLARE
l_employee_id
INT
;
DECLARE
l_salary
NUMERIC
(8, 2);
DECLARE
l_department_id
INT
;
DECLARE
done
INT
DEFAULT
0;
DECLARE
curl
CURSOR
FOR
SELECT
employee_id, salary, department_id
FROM
employees;
DECLARE
CONTINUE
HANDLER
FOR
NOT
FOUND
SET
done = 1;
OPEN
curl; emp_loop : LOOP
FETCH
curl
INTO
l_employee_id, l_salary, l_department_id; IF done = 1
THEN
LEAVE emp_loop;
END
IF;
END
LOOP emp_loop;
|
CLOSE curl;
END;$$