文章目录
- 什么是存储过程
- 创建存储过程
- 调用存储过程
- 删除存储过程
- 参数
- 默认参数
- 参数验证
- 输出参数
- 变量
- 用户定义变量
- 本地变量
- 函数
- 创建函数
- 使用函数
- 删除
什么是存储过程
存储过程是一个包含一堆SQL代码的数据库对象,可以在我们编写其他语言程序的时候回,我们可以调用这些过程来获取或保存数据;使用存储过程来存储和管理SQL代码还可以使得在其他语言的函数中不必编写SQL语句,使得代码更加简洁
还有就是存储在数据库中的存储过程的代码DBMS可以对其进行一定的优化,使得访问效率提高
当然还能增强安全性
存储过程思想上很简单,就是数据库 SQL 语言层面的代码封装与重用。
优点:
创建存储过程
DELIMITER //(或者$$)
CREATE PROCEDURE 存储名(参数, ...)
BEGIN
SQL语句主体(body)
注意这里一般会有多条语句,要用分号隔开
END $$ //
修改默认分隔符DELIMETER
有的sql是不需要的
使用这个目的相当于告诉MySQL,这整段都要进入存储过程里保存
注意,选择好你要存储的数据库进行创建
delimiter $$
create procedure get_invoices_with_balance()
begin
select
*
from invoices
where (invoice_total - payment_total) > 0;
end $$
调用存储过程
CALL 名字(参数)
多数时候,我们用其他语言来调用存储过程,如果在sql里面,需要使用CALL
删除存储过程
DROP PROCEDURE 过程名
这种写法如果不存在这个过程的话是会报错的
所以 我们可以这么写
DROP PROCEDURE IF EXISTS 过程名
参数
例如,我们可以按地区查找数据库
delimiter $$
create procedure get_client_by_state(state char(2))
begin
select * from clients c where c.state = state;
end $$
如果此时调用该存储过程不加参数是会报错的,下面介绍默认参数
默认参数
如果调用时里面不含任何参数,我们可以设置一个默认参数
delimiter $$
create procedure get_client_by_state(state char(2))
begin
if state is null then
set state = 'cA';
end if;
select * from clients c where c.state = state;
end $$
如果我们要求默认情况下返回所有参数
delimiter $$
create procedure get_client_by_state(state char(2))
begin
if state is null then
select * from clients;
else
select * from clients c where c.state = state;
end if;
end $$
还有一种方式
delimiter $$
create procedure get_client_by_state(state char(2))
begin
select * from clients c where c.state = IfNULL(state, c.state);
end $$
ifnull函数判断括号第一个值是不是空值,如果是则返回第二个
参数验证
有的时候我们要往数据库里插入一些数据,但是我们不能保证有的时候传入的数据一定是正确的,所以我们要进行一些判断,就是参数验证
delimiter $$
create procedure get_payments(client_id int, payment_method_id tinyint) -- 非必须参数
begin
select *
from payments p
where p.client_id = ifnull(client_id, p.client_id)
and p.payment_method_id = ifnull(payment_method_id, p.payment_method_id);
end $$
如果上面的client_id为负数怎么办?
我们可以写一个if函数
delimiter $$
create procedure get_payments(client_id int, payment_method_id tinyint) -- 非必须参数
begin
if client_id < 0 then
signal sqlstate '22003' set message_text = '123456'; -- singal相当于其他语言的抛出错误异常,这里就是抛出sql错误码
-- 然后可以设置一下要抛出的错误信息
end if;
select *
from payments p
where p.client_id = ifnull(client_id, p.client_id)
and p.payment_method_id = ifnull(payment_method_id, p.payment_method_id);
end $$
输出参数
在参数设置中,我们加入OUT
关键词来标注这个参数最后是要输出的
delimiter $$
create procedure get_unpaid_invoices_for_client(
client_id int,
out invoices_count int,
out invoices_total decimal(9, 2) -- 这里是小数的意思,保留两位小数,精度为9,也就是小数点前有7位
)
begin
select
count(*),
sum(invoice_total)
into
invoices_count,
invoices_total -- 输出参数要一一对应
from invoices i
where i.client_id = client_id and payment_toatal = 0;
end $$
这时候调用的过程也发生了变化
set @invoices_total = 0; -- 定义两个用户定义变量
set @invoices_count = 0; -- 使用前缀@来定义
call sql_invoicing.get_unpaid_invoices_for_client(1, @invoices_count, @invoices_total);
-- 当调用这个过程的时候,我们要往里面传入这些变量用于接收
select @invoices_count, @invoices_total;
变量
通常我们会在调用有输出参数的存储过程时使用这些变量
用户定义变量
传递这些变量,来获取输出参数值,这些变量在整个客户会话股哟称重被保存,客户从MySQL断线时,这些变量又被清空
用set定义,@作为前缀
本地变量
这是我们可以在存储过程或者函数内定义的
这些变量不会在整个客户端会话过程中保存
一旦存储过程结束,变量就会清空
使用declare
定义变量
declare a decimal(9, 2) default 0;
set a = 1.1; -- .....自己变换
函数
与存储过程的区别是函数只能返回单一值
创建函数
create function 函数名
(
参数
)
returns 类型
函数属性(deterministic...可以有多个属性)
begin
return
end
函数属性
- deterministic:确定性,给定这个函数同样的一组值,它会永远返回一样的值
- read sql data:函数中会配置选择语句,用以读取一些数据
- modifies data:函数中有插入、更新、删除函数
使用函数
跟调用内置函数一样,就像是调用内置函数
删除
drop function if exists 函数名