
























讲存储过程和函数,帮你把 SQL 查询打包,省事还能复用。跟着注释走,边看边搞。
学习内容
示例代码与讲解
1. 创建存储过程
DELIMITER $$
CREATE PROCEDURE get_clients()
BEGIN
SELECT * FROM clients;
END $$
DELIMITER ;
CALL get_clients();
2. 删除存储过程
DROP PROCEDURE get_clients;
DROP PROCEDURE IF EXISTS get_clients;
3. 带参数的存储过程
DELIMITER $$
CREATE PROCEDURE get_clients_by_state(p_state CHAR(2))
BEGIN
SELECT * FROM clients c
WHERE c.state = p_state;
END $$
DELIMITER ;
CALL get_clients_by_state('CA');
4. 带默认值的存储过程
DELIMITER $$
CREATE PROCEDURE get_clients_by_state(p_state CHAR(2))
BEGIN
IF p_state IS NULL THEN
SET p_state = 'CA';
END IF;
SELECT * FROM clients c
WHERE c.state = p_state;
END $$
DELIMITER ;
CALL get_clients_by_state(NULL);
DELIMITER $$
CREATE PROCEDURE get_clients_by_state(p_state CHAR(2))
BEGIN
IF p_state IS NULL THEN
SELECT * FROM clients;
ELSE
SELECT * FROM clients c
WHERE c.client_id = p_state;
END IF;
END $$
DELIMITER ;
DELIMITER $$
CREATE PROCEDURE get_clients_by_state(p_state CHAR(2))
BEGIN
SELECT * FROM clients c
WHERE c.client_id = IFNULL(p_state, client_id);
END $$
DELIMITER ;
5. 参数验证
DELIMITER $$
CREATE PROCEDURE make_payment(
p_invoices_id INT,
p_payment_amount DECIMAL(9,2),
p_payment_date DATE
)
BEGIN
IF p_payment_amount <= 0 THEN
SIGNAL SQLSTATE '22003'
SET MESSAGE_TEXT = 'Invalid payment
amount';
END IF;
UPDATE invoices i
SET i.payment_total = p_payment_amount,
i.payment_date = p_payment_date
WHERE i.invoice_id = p_invoices_id;
END $$
DELIMITER ;
CALL make_payment(2, -100, '2019-01-01');
6. 输出参数
DELIMITER $$
CREATE PROCEDURE get_unpaid_invoices_for_client(
p_client_id INT,
OUT invoices_count INT,
OUT invoices_total DECIMAL(9,2)
)
BEGIN
SELECT COUNT(*), SUM(i.invoice_total)
INTO invoices_count, invoices_total
FROM invoices i
WHERE i.client_id = p_client_id AND i.payment_total
= 0;
END $$
DELIMITER ;
SET @invoices_count = 0;
SET @invoices_total = 0;
CALL get_unpaid_invoices_for_client(3, @invoices_count, @invoices_total);
SELECT @invoices_count, @invoices_total;
7. 变量
SET @variable_name = 0;
DELIMITER $$
CREATE PROCEDURE get_risk()
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;
SET risk_factor = invoices_total / invoices_count
* 5;
SELECT risk_factor;
END $$
DELIMITER ;
8. 函数
DELIMITER $$
CREATE FUNCTION count_risk_for_client(client_id INT)
RETURNS INT
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;
RETURN IFNULL(risk_factor, 0);
END $$
DELIMITER ;
SELECT client_id, name,
count_risk_for_client(client_id) AS risk
FROM clients;
作业
1. 视图存储过程
DELIMITER $$
CREATE PROCEDURE get_invoices_with_balance()
BEGIN
SELECT * FROM invoices_with_balance
WHERE Balance > 0;
END $$
DELIMITER ;
2. 带参数存储过程
DELIMITER $$
CREATE PROCEDURE get_invoices_by_client(p_client INT)
BEGIN
SELECT * FROM invoices
WHERE invoice_id = p_client;
END $$
DELIMITER ;
CALL get_invoices_by_client(8);
3. 默认值与多参数
DELIMITER $$
CREATE PROCEDURE get_payment(p_client_id INT,
p_pay_method_id TINYINT)
BEGIN
SELECT p.client_id, pm.name
FROM payments p
JOIN payment_methods pm ON p.payment_method =
pm.payment_method_id
WHERE p.client_id = IFNULL(p_client_id,
p.client_id)
AND p.payment_method = IFNULL(p_pay_method_id,
p.payment_method);
END $$
DELIMITER ;
CALL get_payment(5, 4);
总结
讲了存储过程的创建、调用、参数、验证、变量,还搞了个函数,方便复用逻辑。用的 sql_invoicing 数据库。接下来看触发器和事务。
常见的错误对应代码:
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。