【数据库笔记】MySQL必知必会:chapter 23-26 存储过程 | 游标 | 触发器 | 管理事务处理


chapter 23 使用存储过程

MySQL5 添加了存储过程的支持,因此本章适用于MySQL5及以后的版本。

23.1 存储过程

在这里插入图片描述
可以创建存储过程

存储过程简单来说,就是为以后的使用而保存的一条或多条MYSQL语句的集合。可将其视为批文件,虽然它们的作用不仅限于批处理

23.2 为什么要使用存储过程

  • 通过把处理封装在容易使用的单元中,简化复杂的操作
  • 由于不要求反复建立一系列处理步骤,这保证了数据的完整性。如果所有的开发人员和应用程序都使用同一(试验和测试)存储过程,则使用的代码都是相同的。
    这一点能防止错误。需要执行的步骤越多,出错的额可能性就越大。防止错误保证了数据的一致性。
  • 简化对变动的管理。如果表名、列名或业务逻辑(或别的内容)有变化,只需要更改存储过程的代码。
    这一点能确保安全性。通过存储过程限制对基础数据的访问减少了数据讹误。
  • 提高性能。使用存储过程比使用单独的SQL语句要快。
  • 存在一些只能用在单个请求中的MySQL元素和特性,存储过程可以使用它们来编写功能更强更灵活的代码(chapter 24)。

存储过程的3个好处简单、安全、高性能
存储过程的一些缺陷
(1)一般来说,存储过程的编写比基本SQL语句复杂,编写存储过程需要更高的技能,更丰富的经验;
(2)你可能没有创建存储过程的安全访问权限。许多数据库管理员限制存储过程的创建权限,允许用户使用存储过程,但不允许他们创建存储过程

MySQL将编写存储过程的安全和访问执行存储过程的安全和访问区分开来。这是好事情,即使你不能或不想编写自己的存储过程,也仍然可以在适当的时候执行别的存储过程。

23.3 使用存储过程

存储过程的 执行 远比其 定义 更经常遇到。

1.执行存储过程

MySQL称存储过程的执行为调用,因此MySQL执行存储过程的语句为CALL

CALL接受存储过程的名字以及需要传递给它的任意参数

--执行(call)名为productpricing的存储过程
--它计算并返回产品的最低、最高和平均价格
call productpricing(@pricelow,
					@pricehigh,
					@priceaverage);

存储过程可以显示结果,也可以不显示结果。

2.创建存储过程

例子:返回产品平均价格的存储过程

--存储过程名为productpricing
--用create procedure productpricing()定义
--如果存储过程接受参数,它们将在()中列举

--此存储过程没有参数,但是()不省略
--begin和end;语句用来限定存储过程体
--过程体本身只是一个简单的select语句
create procedure productpricing()
begin
	select Avg(prod_price) as priceaverage
	from products;
end;

上述代码没有返回结果,因为只是创建了一个存储过程,但是没有调用存储过程。

mysql命令行客户机的分隔符

默认的MySQL语句分隔符为;

如果命令行实用程序要解释存储过程自身内的;字符,则它们最终不会成为存储过程的成分,这会使存储过程中的SQL出现句法错误。默认情况下,不可能等到用户把这些语句全部输入完之后,再执行整段语句。 因为 mysql一遇到分号,它就要自动执行。
即,在语句RETURN ‘’;时,mysql解释器就要执行了。

解决办法:临时更改命令行实用程序的语句分隔符

DELIMITER //

CREATE procedure productpricing()
beginselect Avg(prod_price) AS priceaverage
​	from products;
end//

DELIMITER;  

其中,delimiter//告诉命令行实用程序实用//作为新的语句结束分隔符;可以看到标志存储过程结束的END定义为END//而不是END;这样,存储过程体内的仍然保持不动,并且正确地传递给数据库引擎。
除了\符号外,任何字符都可以用作语句分隔符。如果你使用的是MySQL命令行实用程序,请注意这一点!

实际上,上面这种一段的独立select或者几段独立的select的不DELIMITER ,也不会出错,个人的理解是,当beginend间的语句,存在;并且之间是有连贯的逻辑性时(如用上了elseif),此时需要用DELIMITER

那么,如何使用这个存储过程?

CALL productpricing();
--返回结果
--+------------+
--|priceaverage|
--+------------+
--|   16.133571|

因为存储过程实际上是一种函数,所以存储过程名后要有()符号,即使没有传递参数也需要。

3.删除存储过程

注意删除语句,没有使用(),只给出存储过程名。

drop procedure productpricing;

仅当存在时删除
如果指定的过程不存在,则drop procedure产生一个错误。
如果过程不存在,也不会产生错误的做法是:使用DROP PROCEDURE IF EXISTS

4.使用参数

productpricing简单的存储过程,显示select语句的结果。

一般,存储过程并不显示结果,而是把结果返回给你指定给的变量

变量(variable):内存中一个特定的位置,用来临时存储数据

productpricing的修改版如下:

create procedure productpricing(
	out p1 decimal(8,2),
	out ph decimal(8,2),
	out pa decimal(8,2)
)
begin
	select Min(prod_price)
	into p1
	from products;
	select Max(prod_price)
	into ph
	from products;
	select Avg(prod_price)
	into pa
	from products;
end;

此存储过程接受3个参数:

  • p1:存储产品最低价格
  • ph:存储产品最高价格
  • pa:存储产品平均价格

每个参数必须具有指定的类型,这里使用十进制值。

关键字OUT指出相应的参数用来从存储过程传出一个值(返回给调用者)。

MySQL支持
IN:传递给存储过程
OUT:从存储过程传出
INOUT:对存储过程传入和传出

调用此存储过程,必须指定3个变量名:

call productpricing(@pricelow,
                   @pricehigh,
                   @priceaverage);

变量名 所有MySQL变量都必须以@开始

在调用时,这条语句并不显示任何数据它返回以后可以显示的变量。

select @pricelow;
select @pricehigh;
select @priceaverage;
select @pricelow, @pricehigh, @priceaverage;

在这里插入图片描述
再来一个类似函数传入参数的例子,INOUT

--创建存储过程ordertotal
--传入参数 IN onumber int
--传出参数 out ototal decimal(8,2)
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;

--调用存储过程
call ordertotal(20005,@total);
--返回显示变量
select @total;

为了得到另一个订单的合集显示,需要再次调用存储过程,然后重新显示变量:

--调用存储过程
call ordertotal(20009,@total);
--返回显示变量
select @total;

5.建立智能存储过程

迄今为止,所有的存储过程基本上都是封装MySQL简单的select 语句。

只有在存储过程内包含业务规则和智能处理时,它们的威力才能真正显现。

场景:需要做订单合计,但需要对合计增加营业税,不过只针对某些顾客(或许是你所在州的那些客户)。那么你要做以下几件事:

  • 获得合计(和之前一样);
  • 把营业税有条件地添加到合计;
  • 返回合计(带或不带税)。
--Name:ordertotal
--Parameters:onumber=order number
--           taxable=0 if not taxable,1 if taxable
--			 ototal =order total variable
-- I. 创建存储过程
CREATE PROCEDURE ordertotal(-- 参数列表
	IN onumber INT,  -- INT类型的输入形参
	IN taxable BOOLEAN, -- BOOLEAN类型的输入形参
	OUT ototal DECIMAL(8,2) -- DECIMAL(8,2)类型的输出形参
)COMMENT 'Obtain order totalm, optionally adding tax' -- 添加存储过程的备注
BEGIN
	-- 1.声明变量, 最后赋值给ototal输出
	DECLARE total DECIMAL(8,2) -- 声明DECIMAL(8,2)类型的变量total用于存储结果的中间中
	-- 2.声明变量 存储税率
	DECLARE taxrate INT DEFAULT 6; -- 声明INT类型的变量taxrate用于存储税率基数。初始化为 6
	
	-- 3.获得订单总额
	SELECT Sum(item_price*quantity)
	FROM orderitems
	WHERE order_num = onumber -- 只统计输入形参onumber 指定的订单号的总额
	INTO total; -- 将总额中间结果存储给total变量
	
	-- 4.判断是否需要缴税
	IF taxable THEN -- 根据输入形参taxable判断是否进行下一步计算
		-- 需要,添加税率
		SELECT total + (total/100 * taxrate) INTO total;
	END IF;
	
	-- 5. 最后将总额中间结果赋值给输出形参ototal
	SELECT total INTO ototal;
END;
-- 2.1 调用存储过程
CALL ordertotal(20005, 0, @total);
-- 2.2 检索返回结果
SELECT @total;
-- 3.1 调用存储过程
CALL ordertotal(20005, 1, @total);
-- 3.2 检索返回结果
SELECT @total;

在这里插入图片描述在这里插入图片描述在这里插入图片描述

6.检查存储过程

为显示用来创建一个存储过程的create语句,使用show create procedure

show create procedure ordertotal;

为获得包括何时、由谁创建等详细信息的存储过程列表,使用show procedure status,会列出所有的存储过程,为限制输出,可用like指定一个过滤模式:

show procedure status like 'ordertotal';

chapter 24 使用游标

MySQL5 添加了游标的支持,因此本章适用于MySQL5及以后的版本。

24.1 游标

MySQL检索操作返回一组称为结果集的行。

使用游标的原因:有时,需要在检索出来的行中 前进 或者 后退 一行或多行

游标:是一个存储在MySQL服务器上的数据库查询,它不是一条SELECT语句,而是被SELECT语句检索出来的结果集。在存储了游标之后,应用程序可以根据需要滚动或浏览其中的数据

游标主要用于交互式应用,其中用户需要滚动屏幕上的数据,并对数据进行浏览或做出更改。

只能用于存储过程 不像多数DBMS,MySQL游标只能用于存储过程(和函数)。

24.2 使用游标

使用游标及几个明确的步骤:

  1. 在能够使用游标前,必须声明(定义)它。这个过程实际上没有检索数据,它只是定义要使用的SELECT语句
  2. 一旦声明后,必须打开游标以供使用。这个过程用前面定义的SELECT语句把数据实际检索出来
  3. 对于填有数据的游标,根据需要取出(检索)各行
  4. 在结束游标使用时,必须关闭游标

1.创建游标

游标用DECLARE语句创建。DECLARE命名游标,并定义相应的SELECT语句,根据需要带WHERE和其他子句。例如,以下语句定义了名为ordernumbers的游标,使用了可以检索所有订单的SELECT语句。

--DECLARE语句用来定义和命名游标(ordernumbers)
--存储过程处理完成后,游标就会消失(因为它局限于存储过程)
create procedure processorders()
begin
	declare ordernumbers cursor
	for 
	select order_num from orders;
end;

2.打开和关闭游标

打开游标

open ordernumbers;

在处理open语句时执行查询,存储检索出的数据以供浏览和滚动。

关闭游标

close ordernumbers;

close释放游标使用的所有内存和资源,因此在每个游标不再需要时,都应该关闭!
关了以后就不能用了,但是已经申明过了就不需要再申明,还要用再open即可。

隐含关闭 如果不明确close,MySQL将会在到达END语句时自动关闭它。

下面是上述例子的修改版本:
包含了 声明、打开和关闭 一个游标,但是对检索出的数据啥也没干

create procedure processorders()
begin
	--声明游标ordernumbers
	declare ordernumbers cursor
	for
	select order_num from orders;

	--打开游标
	open ordernumbers;
	
	--关闭游标
	close ordernumbers;
end;

3.使用游标数据

在一个游标open后,可以使用fetch语句分别访问它的每一行。

fetch语句会:

  1. 指定检索什么数据(所需的列)
  2. 检索出来的数据存储在什么地方
  3. 向前移动游标中的内部行指针,使下一条fetch语句检索下一行(不重复读取同一行)。

例1:从游标中检索单个行(第一行)

create procedure processorders()
begin
	--声明局部变量
	declare o int;
	
	--声明游标ordernumbers
	declare ordernumbers cursor
	for
	select order_num from orders;

	--打开游标
	open ordernumbers;

	--获得订单号order_num
	fetch ordernumbers into o;
	
	--关闭游标
	close ordernumbers;
end;

fetch用来检索当前行的order_num列(自动从第一行开始),赋值到一个名为o的局部声明变量中。对检索出的数据不做任何处理

例2:循环检索数据,从第一行到最后一行

create procedure processorders()
begin
	--声明局部变量
	declare done boolean default 0;
	declare o int;
	
	--声明游标ordernumbers
	declare ordernumbers cursor
	for
	select order_num from orders;

	--声明continue handler
	declare continue handler for sqlstate '02000' set done=1;

	--打开游标
	open ordernumbers;

	--循环所有行loop through all rows
	repeat

		--获得订单号order_num
		fetch ordernumbers into o;
	--end of loop
	until done end repeat;
	
	--关闭游标
	close ordernumbers;
end;

FETCH用来检索当前行的order_num列到一个名为o的局部声明的变量中。

与例1不同之处在于FETCHREPEAT内,因此它反复执行直到done为真(由until done end repeat;规定)。

为了使它起作用,用一个DEFAULT 0(假,不结束)定义变量done。以下的语句可以将done设置为真:

--声明continue handler
declare continue handler for sqlstate '02000' set done=1;

这条语句定义了一个continue handler,它是在条件出现时被执行的代码,它指出当sqlstate '02000' 出现时,set done=1sqlstate '02000'是一个未找到条件,当repeat由于没有更多的行供循环而不能继续时,出现这个条件。

DECLARE语句的次序
DECLARE语句定义的局部变量必须在定义任意游标或句柄之前定义,不遵守此顺序将产生错误消息。

如果调用这个存储过程,它将定义几个变量和一个continue handler,定义并打开一个游标,重复读取所有行,然后关闭游标。如果一切正常,可以在循环内放入任意需要的处理(在 fetch语句之后,循环结束之前)。

create procedure processorders()
begin
	--声明局部变量
	declare done boolean default 0;
	declare o int;
	declare t decimal(8,2);
	
	--声明游标ordernumbers
	declare ordernumbers cursor
	for
	select order_num from orders;

	--声明continue handler
	declare continue handler for sqlstate '02000' set done=1;

	--创建一个表存结果
	create table if not exists ordertotals
	(order_num int,
	total decimal(8,2));
	
	--打开游标
	open ordernumbers;

	--循环所有行loop through all rows
	repeat

		--获得订单号order_num
		fetch ordernumbers into o;

		--获得每个订单的合计total
		--call另一个存储过程来计算每个订单的带税合计(结果存储到t)
		call ordertotal(o,1,t);

		--插入订单量和total信息仅ordertotals表
		insert into ordertotals(order_num,total) values(o,t)
	--end of loop
	until done end repeat;
	
	--关闭游标
	close ordernumbers;
end;

--返回数据
select *
from ordertotals;

在这里插入图片描述

chapter 25 使用触发器

MySQL5 添加了触发器的支持,因此本章适用于MySQL5及以后的版本。

25.1 触发器

MySQL语句在需要时被执行,存储过程也是如此。但是,如果要某条(或某些语句)在事件发生时自动执行,怎么办呢?

  • 每当增加一个顾客到某个数据库表时,都检查其电话号码格式是否正确,州的缩写是否为大写
  • 每当订购一个产品时,都从库存数量中减去订购的数量;
  • 无论何时删除一行,都在某个存档表中保留一个副本。

上述例子的共同之处:它们都需要在某个表发生变化时自动处理,这确切的讲就是触发器

触发器是MySQL响应以下任意语句(deleteinsertupdate)而自动执行的一条MySQL语句(或位于beginend语句之间的一组语句)。

只有deleteinsertupdate这3条语句支持触发器,其他MySQL语句不支持。

25.2 创建触发器

创建触发器时,需要给出4条信息:

  1. 唯一的触发器
  2. 触发器关联的表
  3. 触发器应该响应的活动(deleteinsertupdate)
  4. 触发器何时执行 (处理前 / 处理后)
    在这里插入图片描述
    触发器使用create trigger语句创建:
create trigger newproduct after insert on products
for each row select 'Product added' into @res

create trigger用来创建一个名为newproduct的新触发器,触发器可在一个操作发生之前之后执行,after insert用来表明触发器将在insert语句成功执行后执行。

这个触发器还指定了for each row因此代码对每个插入行执行,文本'Product added'将对每个插入的行显示一次

为了测试这个触发器,使用insert语句添加一行或多行到products中,你将看到每个成功的插入,显示'Product added'消息。

仅支持表
只有表才能使用触发器,视图和临时表不支持使用触发器

在这里插入图片描述

触发器按 每个表 每个事件 每次 地定义,每个表 每个事件 每次只允许一个触发器,因此一个表最多支持6个触发器(每条deleteinsertupdate的之前或之后)

单一触发器不能和 多个事件多个表 关联,所以如果需要一个对insertupdate操作执行的触发器应该定义 2 个触发器

触发器失败
如果before触发器失败,则MySQL将不执行请求的操作。此外,如果before触发器或语句本身失败,MySQL将不执行after触发器(如果有)。

25.3 删除触发器

触发器不能更新或覆盖,为了修改一个触发器,必须先删除它,然后再重新创建。

删除一个触发器,可以使用drop trigger语句:

drop trigger newproduct;

25.4 使用触发器

1.insert触发器

insert触发器insert语句执行之前或之后发生,需要明白几点:

  1. insert触发器代码中,可引用一个名为new的虚拟表,访问被插入的行;
  2. before insert触发器中,new中的值可以被更新(允许更改被插入的行);
  3. 对于auto_increment列,newinsert执行之前为0,在insert执行后包含新的自动生成值。
create trigger neworder after insert on orders
for each row select new.order_num;

此代码创建一个名为neworder的触发器
它按照after insert on orders执行。

在插入一个新订单到orders表时,MySQL生成一个新订单号并保存到order_num中。

触发器从new.order_num中取得这个值并返回它。此触发器必须按照after insert执行,因此在before insert执行之前,新order_num还没有生成。

对于orders的每次插入使用这个触发器将总是返回新的订单号.

为了测试这个触发器,试着插入一下新行:

insert into orders(order_date,cust_id)
values(now(),10001);

在这里插入图片描述

beforeafter
通常,将before用于数据验证和净化(保证处理的数据是需要的数据)

drop trigger newproduct;
create trigger newproduct after insert on stu
for each row select 'new sutudent added' into @res;

insert into stu(id,s_name) values(888,'你好毒');
select @res;

在这里插入图片描述

2.delete触发器

delete触发器delete语句执行之前或执行后执行。

  1. delete触发器代码内,可引用一个名为old的虚拟表,访问被删除的行;
  2. old中的值都是只读的,不能更新。
create trigger deleteorder before delete on orders
for each row
begin
	insert into archive_orders(order_num, order_date, cust_id)
	values(old.order_num,old.order_date,old.cust_id);
end;

上述deleteorder触发器在任意行被删除,使用一条insert语句将old中的值(要删除的订单)保存到一个名为archive的存档表中

DELETE FROM orders
WHERE order_num= 10006;

触发器中也可以使用多条begin end语句,它的好处是使触发器能容纳多条SQL语句

3.update触发器

update触发器update语句执行前或执行后执行。

  1. update触发器代码中,可以引用一个名为old的虚拟表访问以前(执行update语句)的值,可以引用一个名为new的虚拟表访问更新后(执行update语句)的值;
  2. before update触发器中,new中的值也可能被更新(允许更改将要用于update语句中的值);
  3. old中的值全都是只读的,不可更新。
create trigger updatevendor before update on vendors
for each row
set new.vend_state=upper(new.vend_state)

上述语句完成了保证了州名的缩写总是大写,显然任何数据净化都需要在update之前完成

25.5 进一步了解触发器

  1. 创建触发器可能需要特殊的安全访问权限,但是触发器的执行是自动的,如果insertupdatedelete语句能够执行,则相关的触发器也能执行
  2. 应该用触发器来保证数据的一致性(大小写,格式统一),在触发器中执行这种类型的处理是它总是进行这种处理,而且是透明地进行,与客户机无关;
  3. 触发器的一种非常有意义的作用是创建审计跟踪,使用触发器,可以把更改的行记录到另一个表中(如果需要,甚至还有之前和之后的状态)

chapter 26 管理事务处理

26.1 事务处理

并非所有的引擎都支持事务处理 MySQL支持几种基本的数据库引擎,MyISAM和InnoDB是两种最常用的引擎,但MyISAM不支持事务处理,而InnoDB支持,如果你的应用中需要事务处理,则一定要选择正确的引擎来创建表。

事务处理transaction processing):可以用来维护数据库的完整性它保证成批的MySQL操作要么完全执行,要么完全不执行

:订单存储在ordersorderitems两个表中。这两个表用主键的唯一ID相关联,这两个表又与包含客户和产品信息的其它表相关联。

  • orders:存储实际的订单
  • orderitems:存储订单的各项物品

给系统添加新订单,过程如下:

  1. 检查数据库中是否存在相应的客户,如果不存在则添加他;
  2. 检索客户的ID
  3. 添加一行到orders表中,把它和客户ID关联
  4. 检索orders表中赋予的新订单ID
  5. 对于订购的每个物品在orderitems表中添加一行,通过检索出来的ID把它与orders表相关联

现在假如由于某种数据库故障(如超出磁盘空间,安全限制,表锁)等阻止了这个过程数据库中的数据会出现几种情况

  1. 如果故障发生在添加了客户后,orders表添加之前,不会有什么问题,某些客户没有订单是合法的,在排错后重新执行此过程时,所插入的客户记录将被检索和使用,可以有效地从故障发生的地方开始继续执行;
  2. 如果故障发生在orders行添加之后,orderitems行添加之前,会导致数据库中出现一个空订单;
  3. 如果系统在添加orderitems行中出现错误,结果是数据库中存在不完整的订单

解决方案:使用事务处理。

事务处理是一种机制,用来管理成批的MySQL操作,以保证数据库不包含不完整的操作结果。利用事务处理,可以保证一组操作不会中途停止,它们作为整体一起执行,或者全部不执行

  • 如果没有错误发生,整组语句提交给数据库表
  • 如果发生了错误,则进行回退以恢复数据库到某个已经且安全的状态

因此,对这个例子,再次说明使用了事务处理后的例子如何工作:

  1. 检查数据库中是否存在相应的客户,如果不存在则添加他;
  2. 提交客户信息;
  3. 检索客户的ID;
  4. 添加一行到orders表;
  5. 如果在添加行到orders表时,出现故障,回退;
  6. 检索orders表中赋予的新订单ID;
  7. 对于订购的每个物品在orderitems表中添加一行;
  8. 如果在添加行到orderitems表时,出现故障,回退到没有添加的orderitems行和orders行;
  9. 提交订单信息。

使用事务处理的几个术语:

  1. 事务transaction):指一组SQL语句;
  2. 回退rollback):指撤销指定SQL语句的过程 ;
  3. 提交commit):指将未存储的SQL语句结果写入数据库表
  4. 保留点savepoint):指事物处理中设置的临时占位符,可以对它发布回退(与回退整个事物处理不同)

26.2 控制事务处理

管理事务处理的关键:将SQL语句分解为逻辑块,并明确规定数据何时应该回退,何时不应该回退。

MySQL使用以下语句标志事物的开始:

start transaction;

1 使用rollback

MySQL的rollback命令用来回退(撤销)MySQL语句。

--事务处理前,查询ordertotals原表
select * from ordertotals;

--开始事务
start transaction;
delete from ordertotals;--删除ordertotals表
select * from ordertotals;--返回空表,删除后的ordertotals表
--回退
rollback;
select * from ordertotals;--返回ordertotals原表

首先,执行一条select语句显示该表不为空。

然后,开始一个事务处理,用一条delete语句删除ordertotals表中的所有行。紧接的一条select语句验证ordertotals表已经为空。

rollback语句回退start transaction之后的所有语句。

最后,select语句显示该表不为空。

rollback语句只能在一个事务处理内使用(在执行一条start transaction命令之后)

哪些语句可以回退?
事务处理用来管理insertupdatedelete语句,不能回退select语句不能回退createdrop操作,事物处理块中可以使用createdrop这两条语句,但如果执行回退,它们不会被撤销

2 使用commit

一般的MySQL语句但是直接对数据库表执行和编写的,这就是所谓的隐含提交implicit commit),即提交(写或保存)操作是自动进行的。

但是事务处理过程中,提交不会隐含地进行,需要使用commit语句进行明确地提交。

start transaction;
delete from orderitems where order_num = 20010;
delete from orders where order_num = 20010;
commit;

上述例子涉及到了两个表,所以使用事务处理块来保证订单不被部分删除,最后的commit语句仅在不出错时写出更改,如果第一条delete起作用,但第二条失败,则delete不会提交(实际上它被自动撤销)

隐含事务关闭
commitrollback执行后,事务会自动关闭将来的更改会隐含提交

3 使用保留点

简单的rollbackcommit语句可以撤销或写入整个事务处理,但只能处理简单的事物处理,更复杂的事务处理可能需要部分提交或回退。

为了支持部分提交或回退,必须能在事务处理块中找到合适的位置放置占位符,这样当需要回退时可以回退到某个占位符,这些占位符称为保留点savepoint)。

创建保留点:

savepoint delete1;

每个保留点都有它的唯一名字以便在回退时,MySQL知道要回退到何处

回退到保留点:

rollback delete1;

保留点越多越好:因为保留点越多,就能越灵活地进行回退

释放保留点:在事务处理完成后自动释放(执行完一条rollbackcommit)。自MySQL5以来,也可以用release savepoint明确地释放保留点。

4 更改默认的提交行为

默认的MySQL行为是自动提交所有更改,即任何时候执行一条MySQL语句,该语句实际上都是针对表执行的,而且所做的更改立刻生效

为指示MySQL不自动提交,需要使用

set autocommit = 0

autocommit:决定是否自动提交更改,不管有没有commit语句。设置autocommit=0(假)指示MySQL不自动提交更改,直到autocommit=1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值