19、使用存储过程
MySQL的存储过程的语句跟这本书上的差太远了吧,以下参考自:MySQL存储过程教程
DELIMITER // -- 先把分隔符“;”换成“//”,以免非预期的语句结束
CREATE PROCEDURE mailing_list_count(
OUT list_count INT
-- OUT表示该参数用来返回值
-- IN表示用来传递值
-- INOUT更多查看上面的参考
)
BEGIN
DECLARE v_rows INT;
SELECT COUNT(*) INTO v_rows
FROM customers
WHERE NOT cust_email IS NULL;
SET list_count = v_rows;
END// -- 这里才是这整个CREATE PROCEDURE语句的结束
DELIMITER ; -- 恢复分隔符为“;”,注意有个空格
CALL mailing_list_count(@count); -- 调用存储过程
SELECT @count; --查看count的值
20、管理事务处理
事务处理用来确保一连串相关的表操作,能够全部执行完毕,如果其中某步骤出错,则进行回滚。
比如1个新顾客,下了1个订单,其中有2个商品,将涉及到3个表的操作。
可以撤销的操作:INSERT、UPDATE、DELETE,不能撤销的操作:SELECT、CREATE、DROP。
嗯,,,这个书上的例子,完全不能用在MySQL中
BEGIN; -- 或者START TRANSACTION;
DELETE FROM orders WHERE order_num = 343242;
COMMIT; -- 在执行COMMIT前,都可以用ROLLBACK撤销之前的所有操作
-- 带保留点的回滚
BEGIN;
DELETE FROM orders WHERE order_num = 123;
SAVEPOINT delete1;
DELETE FROM orders WHERE order_num = 1212;
DELETE FROM orders WHERE order_num = 231;
ROLLBACK TO delete1; -- 只撤销SAVEPOINT delete1这句(保留点)之后的语句
21、使用游标
这里由于书上的例子完全不太适用于MySQL,所以参考:《MySQL必知必会》
首先MySQL中的游标只能在存储过程中,然后是只读,只能往一个方向移动,不能跳行
先定义另一个要用到的存储过程
DELIMITER //
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//
DELIMITER ;
循环使用游标,如果不用循环的话,相当于只读取了第一行
DELIMITER //
CREATE PROCEDURE ProcessOrders()
BEGIN
-- 定义局部变量
DECLARE done BOOLEAN DEFAULT 0;
DECLARE o INT;
DECLARE t DECIMAL(8, 2);
-- 定义游标
DECLARE OrderNumbers CURSOR
FOR
SELECT order_num FROM orders;
-- 定义CONTINUE HANDLER
-- SQLSTATE '02000'是一个未找到条件,当REPEAT由于没有更多的行供循环而不能继续时,出现这个条件。
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
-- 创建一个新表用来存储数据,如果该表不存在的话
CREATE TABLE IF NOT EXISTS ordertotals(
order_num INT, total DECIMAL(8, 2)
);
OPEN OrderNumbers;
REPEAT
-- 读取一行,下一次将读取下一行
FETCH OrderNumbers INTO o;
CALL OrderTotal(o, t); -- 调用前面的存储过程,返回总价,存储在变量t中
INSERT INTO ordertotals(order_num, total)
VALUES(o, t);
UNTIL done END REPEAT;
CLOSE OrderNumbers;
END//
DELIMITER ;
调用存储过程,会在表ordertotals(如果不存在,则先创建)中插入,每个订单的总价值
CALL ProcessOrders();
SELECT * FROM ordertotals;
-- 输出,这里为什么会有2个20008?没搞清楚,,
+-----------+---------+
| order_num | total |
+-----------+---------+
| 20005 | 1648.00 |
| 20009 | 1867.50 |
| 20006 | 329.60 |
| 20007 | 1696.00 |
| 20008 | 189.60 |
| 20008 | 189.60 |
+-----------+---------+
《SQL必知必会》最后一章就直接过目一下了,之后再来扫一遍《MySQL必知必会》当作加深记忆,因为现在根本用不到,所以就多看一遍,不然很快就忘了
参考:SQL必知必会(第四版)
参考:MySQL必知必会