delimiter $$
create procedure get_clients()
begin
select * from clients;
end$$
delimiter ;
运行结果:此时生成了一个对应名字的存储过程。
call get_clients()
运行结果:调用了存储过程中的sql语句
将已有的存储过程删除后,继续执行删除操作的话会报错。
因此可把删除存储过程的语句改成:drop procedure if exists,这样删除一个不存在的存储过程时不会报错,更安全。
delimiter $$
create procedure get_invoices_with_balance()
begin
select *
from invoices_with_balance
where balance > 0;
end$$
delimiter ;
运行结果:
call get_invoices_with_balance()
运行结果:
drop procedure if exists get_clients_by_state;
delimiter $$
create procedure get_clients_by_state
(
state char(2)
-- char(2)代表有2个字符的字符串,例如CA, NY
-- varchar代表可变长度的字符串,在存储姓名、电话、信息时很有用
-- 多数时候用varchar,除非能确定字符串有固定长度
)
begin
select * from clients c
where c.state = state;
end $$
delimiter ;
-- 调用时要传参数
call get_clients_by_state('CA')
drop procedure if exists get_invoices_by_client;
delimiter $$
create procedure get_invoices_by_client
(
client_id int
)
begin
select * from invoices i
where i.client_id = client_id;
end $$
delimiter ;
call get_invoices_by_client(3)
运行结果
begin
if 参数 is null then
-- 如果参数为空,就给参数设置一个返回值
set 参数 = 默认值;
-- 或者,参数为空时,直接查询何种结果。
select * from clients;
end if;
……
end
drop procedure if exists get_clients_by_state;
delimiter $$
create procedure get_clients_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 ;
call get_clients_by_state(null)
返回结果:
drop procedure if exists get_clients_by_state;
delimiter $$
create procedure get_clients_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 ;
call get_clients_by_state(null)
运行结果
drop procedure if exists get_clients_by_state;
delimiter $$
create procedure get_clients_by_state
(
state char(2)
)
begin
select * from clients c
-- ifnull:如果为state为空,就返回c.state.
where c.state = ifnull(state, c.state);
end $$
delimiter ;
call get_clients_by_state(NULL)
返回结果:因为传入的参数是null,所以ifnull函数就将c.state传过去,这样就相当于c.state = c.state,会返回所有数据
drop procedure if exists get_payments;
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 = ifnull(payment_method_id, p.payment_method);
end $$
delimiter ;
call get_payments(null,null);
call get_payments(1,null);
call get_payments(null,2);
call get_payments(5,1);
运行结果1:
运行结果2:
运行结果3:
运行结果4:
drop procedure if exists make_payments;
delimiter $$
create procedure make_payments
(
invoice_id int,
payment_amount decimal(9,2), -- 9代表位数,2代表小数点后的位数
payment_date date
)
begin
update invoices i
set -- 只更新两列
i.payment_total = payment_amount,
i.payment_date = payment_date
where i.invoice_id = invoice_id;
end $$
delimiter ;
call make_payments(2,100,'2019-01-01')
结果:invoices表被更新了,id为2的数据被更新了。
call make_payments(2,-100,'2019-01-01')
结果:
drop procedure if exists make_payments;
delimiter $$
create procedure make_payments
(
invoice_id int,
payment_amount decimal(9,2), -- 9代表位数,2代表小数点后的位数
payment_date date
)
begin
-- 增加参数验证
if payment_amount <= 0 then
signal sqlstate '22003'
set message_text = 'Invalid payment_amount';
end if;
-- 更新数据
update invoices i
set -- 只更新两列
i.payment_total = payment_amount,
i.payment_date = payment_date
where i.invoice_id = invoice_id;
end $$
delimiter ;
call make_payments(2,-100,'2019-01-01')
结果:此时会出现错误提示
drop procedure if exists get_unpaid_invoices_for_client;
delimiter $$
create procedure get_unpaid_invoices_for_client
(
client_id int
)
begin
select count(*), sum(invoice_total)
from invoices i
where i.client_id = client_id and payment_total = 0;
end $$
delimiter ;
call get_unpaid_invoices_for_client(3)
drop procedure if exists get_unpaid_invoices_for_client;
delimiter $$
create procedure get_unpaid_invoices_for_client
(
client_id int,
-- out会把参数标记为输出参数
out invoices_count int,
out invoices_total decimal(9,2)
)
begin
select count(*), sum(invoice_total)
into invoices_count, invoices_total
from invoices i
where i.client_id = client_id and payment_total = 0;
end $$
delimiter ;
-- 用set语句定义用户变量
set @invoices_count = 0;
set @invoices_total = 0;
call get_unpaid_invoices_for_client(3, @invoices_count, @invoices_total);
select @invoices_count, @invoices_total;
-- 用set语句定义用户变量
set @invoices_count = 0;
set @invoices_total = 0;
call get_unpaid_invoices_for_client(3, @invoices_count, @invoices_total);
select @invoices_count, @invoices_total;
drop procedure if exists get_risk_factor;
delimiter $$
create procedure get_risk_factor()
begin
declare risk_factor decimal(9,2) default 0;
declare invoices_total decimal(9,2);
declare invoices_count int;
select count(*), sum(invoice_total)
into invoices_count, invoices_total
from invoices i;
set risk_factor = invoices_total / invoices_count * 5;
select risk_factor;
end $$
delimiter ;
运行结果
drop function if exists get_risk_factor_for_client;
create function get_risk_factor_for_client
(
client_id int
)
-- 明确返回值的类型
returns integer
-- 设置函数属性
reads sql data
begin
-- 声明变量
declare risk_factor decimal(9,2) default 0;
declare invoices_total decimal(9,2);
declare invoices_count int;
-- 给变量赋值
select count(*), sum(invoice_total)
into invoices_count, invoices_total
from invoices i
where i.client_id = client_id;
-- 定义变量
set risk_factor = invoices_total / invoices_count * 5;
-- 函数的返回值,如果为空就返回0
return ifnull(risk_factor, 0);
end
-- 调用函数
select client_id,
name,
get_risk_factor_for_client(client_id) as risk_factor
from clients
运行结果: