19拧簸、使用存儲(chǔ)過(guò)程
MySQL的存儲(chǔ)過(guò)程的語(yǔ)句跟這本書上的差太遠(yuǎn)了吧今艺,以下參考自:MySQL存儲(chǔ)過(guò)程教程
DELIMITER // -- 先把分隔符“;”換成“//”走诞,以免非預(yù)期的語(yǔ)句結(jié)束
CREATE PROCEDURE mailing_list_count(
OUT list_count INT
-- OUT表示該參數(shù)用來(lái)返回值
-- IN表示用來(lái)傳遞值
-- 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// -- 這里才是這整個(gè)CREATE PROCEDURE語(yǔ)句的結(jié)束
DELIMITER ; -- 恢復(fù)分隔符為“;”屎飘,注意有個(gè)空格
CALL mailing_list_count(@count); -- 調(diào)用存儲(chǔ)過(guò)程
SELECT @count; --查看count的值
20会油、管理事務(wù)處理
事務(wù)處理用來(lái)確保一連串相關(guān)的表操作个粱,能夠全部執(zhí)行完畢,如果其中某步驟出錯(cuò)翻翩,則進(jìn)行回滾都许。
比如1個(gè)新顧客,下了1個(gè)訂單嫂冻,其中有2個(gè)商品胶征,將涉及到3個(gè)表的操作。
可以撤銷的操作:INSERT桨仿、UPDATE睛低、DELETE,不能撤銷的操作:SELECT服傍、CREATE钱雷、DROP。
嗯吹零,罩抗,,這個(gè)書上的例子瘪校,完全不能用在MySQL中
BEGIN; -- 或者START TRANSACTION;
DELETE FROM orders WHERE order_num = 343242;
COMMIT; -- 在執(zhí)行COMMIT前澄暮,都可以用ROLLBACK撤銷之前的所有操作
-- 帶保留點(diǎn)的回滾
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這句(保留點(diǎn))之后的語(yǔ)句
21、使用游標(biāo)
這里由于書上的例子完全不太適用于MySQL阱扬,所以參考:《MySQL必知必會(huì)》
首先MySQL中的游標(biāo)只能在存儲(chǔ)過(guò)程中泣懊,然后是只讀,只能往一個(gè)方向移動(dòng)麻惶,不能跳行
先定義另一個(gè)要用到的存儲(chǔ)過(guò)程
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 ;
循環(huán)使用游標(biāo)馍刮,如果不用循環(huán)的話,相當(dāng)于只讀取了第一行
DELIMITER //
CREATE PROCEDURE ProcessOrders()
BEGIN
-- 定義局部變量
DECLARE done BOOLEAN DEFAULT 0;
DECLARE o INT;
DECLARE t DECIMAL(8, 2);
-- 定義游標(biāo)
DECLARE OrderNumbers CURSOR
FOR
SELECT order_num FROM orders;
-- 定義CONTINUE HANDLER
-- SQLSTATE '02000'是一個(gè)未找到條件窃蹋,當(dāng)REPEAT由于沒有更多的行供循環(huán)而不能繼續(xù)時(shí)卡啰,出現(xiàn)這個(gè)條件静稻。
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
-- 創(chuàng)建一個(gè)新表用來(lái)存儲(chǔ)數(shù)據(jù),如果該表不存在的話
CREATE TABLE IF NOT EXISTS ordertotals(
order_num INT, total DECIMAL(8, 2)
);
OPEN OrderNumbers;
REPEAT
-- 讀取一行匈辱,下一次將讀取下一行
FETCH OrderNumbers INTO o;
CALL OrderTotal(o, t); -- 調(diào)用前面的存儲(chǔ)過(guò)程振湾,返回總價(jià),存儲(chǔ)在變量t中
INSERT INTO ordertotals(order_num, total)
VALUES(o, t);
UNTIL done END REPEAT;
CLOSE OrderNumbers;
END//
DELIMITER ;
調(diào)用存儲(chǔ)過(guò)程亡脸,會(huì)在表ordertotals(如果不存在押搪,則先創(chuàng)建)中插入,每個(gè)訂單的總價(jià)值
CALL ProcessOrders();
SELECT * FROM ordertotals;
-- 輸出浅碾,這里為什么會(huì)有2個(gè)20008大州?沒搞清楚,垂谢,
+-----------+---------+
| order_num | total |
+-----------+---------+
| 20005 | 1648.00 |
| 20009 | 1867.50 |
| 20006 | 329.60 |
| 20007 | 1696.00 |
| 20008 | 189.60 |
| 20008 | 189.60 |
+-----------+---------+
《SQL必知必會(huì)》最后一章就直接過(guò)目一下了厦画,之后再來(lái)掃一遍《MySQL必知必會(huì)》當(dāng)作加深記憶,因?yàn)楝F(xiàn)在根本用不到滥朱,所以就多看一遍根暑,不然很快就忘了