UNITLdone END REPEAT;
--Closethe cursor;
CLOSEordernumbers;
END;
在这个例子中,FETCH在REPEAT内,因此它反复执行直到done为真(由UNTIL done END REPEAT;规定)。为使它起作用,用一个DEFAULT 0定义变量done。然后用DECLARE CONTINUE HANDLER FOR SQLSTATE ‘02000’ SET done =1;这条语句定义一个CONTINUEHANDLER,它是在条件出现时被执行的代码。这里,它指出当SQLSTATE ‘02000’出现时,SET done=1。SQLSTATE ‘02000’是一个未找到条件,当REPEAT由于没有更多的行工循环而不能继续时,出现这个条件。这里还调用了另外一个存储过程CALL ordertotal(o,1,t);这是在前一章创建的存储过程,实现计算每个订单带税额合计。此存储过程不返回数据,但它能够创建和填充另一个表。
可以用以下语句执行存储过程和查看存储结果:
mysql> CALL processorders();
mysql> SELECT * FROM ordertotals;
+-----------+---------+
| order_num | total |
+-----------+---------+
| 20005 | 158.86 |
| 20006 | 58.30 |
| 20007 | 1060.00 |
| 20008 | 132.50 |
| 20009 | 40.78 |
+-----------+---------+
6 rows in set (0.00 sec)
这样我们就得到了存储过程,游标,逐行处理以及存储过程调用其他存储工程的一个完整的工作样例。
25.使用触发器
25.1触发器
触发器是MySQL响应一下任意语句而自动执行的一条MySQL语句(或位于BEGIN和END语句之间的一组语句):
DELETE
INSERT
UPDATE
25.2创建触发器
创建触发器时,需要给出4条信息:
1) 唯一的触发器名;
2) 触发器关联的表
3) 触发器应该响应的活动(DELETE、INSERT或UPDATE)
4) 触发器何时执行(处理之前或之后)
只有表可以支持触发器,视图不支持(临时表也不支持)。
CREATE TRIGGER newproduct AFTER INSERT ONproducts FOR EACH ROW SELECT 'd';
这里用CREATE TRIGGER创建一个名为newproduct的新触发器。触发器可在一个操作发生之前或之后执行,这里给出了AFTER INSERT,所以触发器将在INSERT语句成功后执行。这个触发器还制定了FOR EACH ROW,因此代码对每个插入行执行。在这个例子中,文本Product added将对每个插入的行显示一次。PS.在我的MySQL版本中,不能成功实现,会提示不能返回结果集Not allowed to return a result set from a trigger错误。不知道是MySQL版本问题还是MySQL必知必会中的错误。
触发器按每个表每个时间每次的定义,每个表每个时间每次只能定义一个触发器,因此一个表最多支持6个触发器(INSERT,UPDATE和DELETE之前或之后)。
25.3删除触发器:
DROP TRIGGER newproduct;
25.4使用触发器
25.4.1 INSERT触发器
1)在INSERT触发器代码内,可引用一个名为NEW的虚拟表,访问被插入的行;
2)在BEFORE INSERT触发器中,NEW中的值可以被更新(允许更改被插入的值)
3)对于AUTO_INCREMENT列,NEW在INSERRT执行之前包含0,在执行之后包含新的自动生成的值。
CREATE TRIGGER neworder AFTER INSERT ONorders FOR EACH ROW SELECT NEW.ORDER_num;
25.4.2DELETE触发器
1)在DELEYE触发器代码内,你可以引用一个名为OLD的虚拟表,访问被删除的行
2)OLD中的值全部都是只读的,不能更新。
CREATE TRIGGER deleteorder BEFORE DELETE ONorders
FOR EACH ROW
BEGIN
INSERT INTO
archive_orderss(order_num,order_date,cust_id)
VALUES(OLD.order_num,OLD.order_date,OLD.cust_id);
END;
25.5 UPDATE触发器
1)可以用OLD的虚拟表访问以前的值,也可以用名为NEW的虚拟表访问新更新的值
2)在BEFFORE UPDATE触发器中,NEW中的值可能也被更新
3)OLD中的值全部都是只读的,不能更新
26.管理事务处理
事务处理可以用来维护数据库的完整性,它保证成批的MySQL操作要么完全执行,要么完全不执行。
术语:
事务:指一组SQL语句
回退:指撤销指定SQL语句的过程
提交:指将未存储的SQL语句结果写入数据库表
保留点:值事务处理中设置的临时占位符,你可以对它发布回退。
26.1控制事务处理
管理事务处理的关键在于将SQL语句组分解为逻辑块,并明确规定数据何时应该回退,何时不应该回退。
START TRANSACTION//标记是事务开始
26.2使用ROLLBACK
ROLLBACK用来回退MySQL语句
SELECT * FROM ordertotals;
START TRANSACTION;
DELETE FROM ordertotals;
SELECT * FROM ordertotals;
ROLLBACK;
SELECT * FROM ordertotals;
依次执行上面语句,可以看到删除的表格内容又被回退了。
ROLLBACK只能在一个事务处理内使用(在执行一条STARTTRANSACTION命令之后)。
26.3使用COMMIT
一般的MySQL都是直接对数据库表执行和编写的,这是隐含提交。但在事务处理块中,提交不会隐含地进行。为进行明确的提交,使用COMMIT语句,如下所示:
START TRANACTION;
DELETE FROM orderitems WHERE order_num =20010;
DELETE FROM orders WHERE order_num = 20010;
COMMIT;
如果第一条起作用,第二条失败,则事务不处理,也就是两条DELETE不会被提交。
26.4使用保留点
简单的ROLLBACK和COMMIT语句就可以写入或撤销整个事务处理。但是,只是对简单的事务处理才嫩这样做,更复杂的事务处理可能需要部分提交或回退。
为了支持回退部分事务处理,必须使用保留点,可如下使用SAVEPOINR语句:
SAVEPOINT delete1;
每个保留点都表示它的唯一名字,以便回退时,MySQL知道要回退到何处。
ROLLBACK TO delete1;
26.5 更改默认的提交行为
为指示MySQL不自动提交更改,需要使用以下语句:
SET autocommit = 0;
27.全球化和本地化
CREATETABLE mytable
(
Column1 INT,
Co