您的位置:首页 > 数据库 > MySQL

跟我一起学习MySQL技术内幕(第五版):(第三章学习日记13)

2016-06-02 01:07 453 查看
3.4处理序列

3.4.1通用的auto_iucrement属性

3.4.2存储引擎特有的auto_increment属性

3.4.2.1MyISAM表的auto_increment列

3.4.2.2InnoDB表的auto_increment列

3.4.2.3memory表的auto_increment列

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

为达成标识的目的,许多应用都需要生成唯一编号,如成员编号,样品编号或批号,顾客ID,bug报告或者故障报告表标签等.

MySQL提供唯一编号的机制是使用MySQL提供唯一编号的机制是使用auto_increment列属性–它会自动生成序列编号.不过,MySQL所支持的那些存储引擎,处理auto_increment列的方式有所不同.下面的讨论将描述:在一般情况下,auto_increment列是如何工作的;对于特定的存储引擎,它又是如何工作的.

3.4.1通用的auto_increment属性

auto_increment列必须按照以下条件进行定义

1.每个表只能有一个列具有anto_increment属性,并且它应该为整数数据类型(支持浮点型,但是很少用)
2.列必须建立索引.最常见的情况是使用primary key或unique索引,但是也允许使用不唯一的索引.
3.列必须拥有not null 约束条件.即使没有显式的这样声明,MySQL也会自动把列设置为not null.


在创建之后,auto_increment列将具有以下行为.

1.把NULL值插入auto_increment列将引发MySQL自动生成下一个序列编号,并把它插入列.auto_increment序列通常是从一开始,并依次单步递增,因此连续插入表的各行的额序号值将为1,2,3,如此等等.在某些场合,根据所使用的存储引擎的不同,可以显式的设置或重置下一个序列号,或者重复使用已从序列顶端删除的那些序号值.
2.要获得最近生成的序号值,可以调用last_insert_id()来检索它.即使在你根本不知道auto_increment值到底是多少的时候,也可以在后续的语句里引用它.如果在当前会话里,还没有生成过auto_increment值,那么last_insert_id()将会返回0.


last_insert_id()只会依赖于与服务器的当前会话连接所生成的auto_increment值.你可以生成一个序号,接着在同一个会话连接里调用last_insert_id()来检索它.即使其他客户在此期间身材个好难过了他们自己的序号值,也不会出现任何问题.

一次插入多个行的insert语句,将生成多个auto_increment值,last_insert_id()只会返回其中的第一个.

如果使用insert delayed 那么要知道实际插入行时,才会生成auto_increment值,这时就不能依靠last_insert_id()来返回序号值了.

1.在插入一行时,如果不为auto_increment列指定值,则等同于向该列插入一个NULL值,如果ai_col是一个auto_increment列,那么下面这两条语句就是等效的
insert into t (ai_col ,name) values(NULL,'abc');
insert into t uu(name) values('abc');
2.默认情况下,把0插入auto_increment列,等效于插入NULL值.如果启用了SQL的no_auto_value_on_zero模式,那么插入零则会导致存储值为零,而非下一个序号值.
3.如果要插入一行,并未某个拥有唯一索引的auto_increment列指定一个既不为NULL也不为0的值,那么将发生两种情况中的某一种.如果已存在一行使用该值的记录,那么将会发生重复错误.否则,这行会被正常插入,而那个auto_increment列会被色会职位那个给定值.如果该值大于当前的下一个序号值,那么这个序列将被重置,对于随后的行,所使用的编号会继续由该值开始生成.换句话说,即可以插入一行,让其序号值大于当前计数器值,以此达到增大计数器的目的.
4.对于某些存储引擎,从序列顶端删除的值可以被重用.如果把包含最大auto_increment列值的那行删除,那么下次生成新值时可以重用这个最大值.如果把表里的所有记录都删除,那么所有值都可以重用,并且这个序列会重新从一开始
5.如果使用update命令吧auto_increment列的值设置为某个正被其他行使用的值,并且这个列拥有唯一索引,那么会出现一个键重复错误,如果把这个列设置为某个大于所有已有列值的编号值,那么对于随后的行,这个序列从那个值开始继续生成下一个编号.如果把该列更新为零,那么他会被设置为零(无论是否启用no_auto value_on_zero都一样)
6.如果根据auto_increment列的值,使用replace来更新行,那么这个行的auto_increment值将保持不变.如果根据其他具有primary key 或unique索引的列的值,使用replace命令来更新行,那么当你把auto_increment列设置为NULL,或者把它设置为0,而且没有启用no_auto_value_on_zero时,该列的值将被更新为一个新的序号值.


3.4.2存储引擎特有的auto_increment属性

3.4.2.1MyISAM表的auto_increment列

MyISAM存储引擎拥有以下auto_increment特性.

1.MyISAM表里的序列一般是单调的.在一个自动生成的序列里,这些值都是经过严格递增的,并且在行被删除之后,不会被重用.
1)如果使用turncate table清空了表,那么计数器将被重置为从1开始
2)如果在表里使用了复合索引来生成多个序列,那么从序列顶端删除的那些值将被重用(以后再讨论)
2.MyISAM序列将默认从1开始,不过可以在create table 语句里,通过auto_increment=n的 选项显式的指定初始值.


create table  mytb1
(
seq int unsigned not null auto_increment,
primary key(seq)
)engine = MYISAM auto_increment = 1000;


一个表只会有一个auto_increment列,因此末尾的那个auto_increment=n的选项会应用到哪一列,绝不会引起歧义.

3.可以使用alter table 来更改某个已有MyISAM表的当前序列计数器.


alter table mytb1 auto_increment = 2000;


如果想要重用那些从序列顶端删除了的值.你也可以使用这个语句来设置.把编号计数器设置到最低,使得下一个编号只比当前最大序号值多1


alter table mytb1 auto_increment = 1;


不能使用auto_increment选项来把当前计数值设置的比表里当前的最大计数值还小
如果某个auto_increment列包含的值为1~10,那么使用auto_increment= 5来设置这个计数器,得到的下一个自动值仍然为11,而非5.


MyISAM存储引擎支持在同一个表里使用复合(多列)索引,以创建多个相互独立的序列.为利用这个特性,为表创建一个由多列组成的primary key 或unique索引,并把包含auto_increment的那个列作为其中的最后一个.对于该索引最左边的列构成的每一个相异键,auto_increment列将生成一组彼此互相不干扰的序列值.

create table bugs
(
proj_name varchar(20) not null,
bug_id    int unsigned not null auto_increment,
description varchar(100),
primary key (proj_name, bug_id)
)engine = MyISAM;


其中,proj_name 列用于标识项目名,description列用于存放bug描述.bug_id列是一个auto_increment列,通过创建一个与proj_name列相关联的索引,可以为各个项目分别生成一个互不干扰的项目编号.

insert into bugs(proj_name,description)
values('SuperBrowser','bug1 ..............');

insert into bugs(proj_name,description)
values('SuperBrowser','bug2 ..............');

insert into bugs(proj_name,description)
values('SpamSquisher','bug3 ..............');

insert into bugs(proj_name,description)
values('SpamSquisher','bug4 ..............');

insert into bugs(proj_name,description)
values('SuperBrowser','bug5 ..............');


之后表的最终内容如下:

proj_name       bug_id      description
------------------------------------
SpamSquisher         1      bug3 ..............
SpamSquisher         2      bug4 ..............
SuperBrowser         1      bug1 ..............
SuperBrowser         2      bug2 ..............
SuperBrowser         3      bug5 ..............


这个表为每一个项目的bug_id 进行了单独的编号,整个规程与这些项目的行输入顺序毫无关系.在输入另一个项目的行之前,你不用先输出某个项目的所有行

如果使用复合索引来创建多个序列,那么从各个序列顶端删除的值都可以被重用.这与MyISAM表的不重用序号值有所不同.

3.4.2.2InnoDB表的auto_increment列

InnoDB存储引擎拥有以下auto_incremeent特性.

1.在create table语句里,可以使用auto_incremeent = n表选项来色环之初始序列值,并且在表创建之后,还可以使用alter table 来进行更改.
2.从序列顶端删除的值通常不能再用.不过,如果使用turncate table清空表,那么序列将被重置,并重新从1开始编号.此外,在满足后面几个条件时也可以重用.
首先,在首次为auto_incremeent列生成序号值时,InnoDB会把列的当前最大值加上1,得到的结果作为新生成的序号值(此前为空的话,序号值为1)
其次,为满足生成后续序号值的需要,InnoDB是在内存里维护这个计数器--它并未存储在表内部.这意味着,如果从这个序列的顶端删除了某些值,

然后又启动了服务器,那么这些删除的值将会被重用.重启服务器还将取消在create table 或alter table语句里使用auto_incremeent表选项所带来的效果.
3.如果生成auto_incremeent值的事务被回滚,那么在序列里可能会出现断裂
4.在表里,不能使用复合索引生成多个独立的序列.


3.4.2.3memory表的auto_increment列

memory存储引擎拥有以下auto_incremeent特性

1在create table 语句里,可以使用auto_incremeent=n 表选项来设置初始序列值,并且在表创建之后,还可以使用alter table 来进行更改.
2.从序列顶端删除的值通常不能再重用.不过,如果使用turncate table 清空表,那么序列将被重置,并重新从1开始编号.
3.在表里,不能使用复合索引生成多个独立的序列.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mysql