我们在设计数据表时,使用自动增长字段可以简化字段数据的生成,在开发实践中,经常将主键设置为自动增长字段,不同的数据库自动增长字段实现是不同的,下面我们一起来详细了解。
15.1 MySQL 中使用自增字段
首先了解下怎么在 MySQL 中创建自增字段,在 MySQL 中创建自增字段比较简单,只需要在字段后面加上 auto_increment 即可:
create table t_test(id int primary key auto_increment, name varchar(20))
上面例句创建了测试表 t_test,表中字段 id 被设置为自动增长的主键,它的默认初始值 1 且步长为 1。使用下面的语句向 t_test
表中插入数据:
insert into t_test (name) values('a');
insert into t_test (name) values('b')
通过查询语句查询插入后的数据:
select * from t_test
结果集:
从结果可以看出,虽然上面 insert 语句没有向主键 id 字段插入数据,但数据库自动向 id 字段插入数据,数据为初始值为 1 步长为 1 的值。
如果希望自己设定表的自增字段初始值,可以使用下面的 SQL 来完成:
ALTER TABLE t_test AUTO_INCREMENT = 5
例句中的 5 是自己设置的,而且需要大于自增字段 id 的当前最大值 2,如果小于则无效。执行上面SQL 后,当再次向表中新增数据时:
insert into t_test (name) values('c');
select * from t_test
结果集:
id 的值从 5 开始自增。如果希望修改自增步长,MySQL 数据库还提供了系统参数 auto_increment_increment
来控制自增步长,以方便进行个性化的设置。现在我们执行下面的SQL语句:
SET session auto_increment_increment=2;
insert into t_test (name) values('d'); select * from t_test
上面SQL语句中SET session auto_increment_increment=2 将本会话中的自增长步长修改为2,然后向表中新增一条记录,从执行结果看,表t_test的id从5增长到了7,说明步长变成了2。
结果集:
15.2 SQLServer 中使用自增字段
在 SQLServer 中为一个字段设置自动增长也比较简单,只需要指定字段为 IDENTITY 即可,比如我们在SQLServer 中创建 t_test 表:
create table t_test(id int PRIMARY KEY IDENTITY(1,1), name nvarchar(20))
在建表语句 IDENTITY(1,1) 中的第一个参数值 1 表示初始值为 1,第二个参数值 1 代表步长为 1。新增两条记录:
insert into t_test (name) values('a');
insert into t_test (name) values('b');
select * from t_test
结果集:
和 MySQL 的效果一样,id 字段按照初始值为 1 步长为 1 的规则自动填充数据。SQLServer 提供了修改自增字段初始值的方法:
DBCC CHECKIDENT ('t_test', RESEED, 10)
语句中参数 10 是设置值,该值必须大于自增字段的最大值,否则新增记录时会报出 id 重复的错误提示。
15.3 Oracle 中使用自增字段
上面我们讲解了如何在 MySQL 和 SQLServer 中使用自增字段,还是比较简单的,但是在 Oracle 中使用自增字段就稍微有点麻烦了,由于没有像 MySQL 那样的 auto_increment 的属性标识,所以需要手工创建序列 sequence,首先创建一张表:
create table t_test(id number , name varchar2(20))
并为该表创建一个对应的序列:
create sequence t_test_id_seq
increment by 1
start with 1
nomaxvalue
nominvalue
nocache
-
increment by:指定了自增步长为1;
-
start with:指定了初始值为1;
-
Maxvalue:用于指定序列生成器可以生成的最大序列号(必须大于或等于start with,并且必须大于 minvalue),默认为 nomaxvalue;
-
Minvalue:用于指定序列生成器可以生成的最小序列号(必须小于或等于start with,并且必须小于maxvalue),默认值为 nominvalue;
-
Cache:用于指定在内存中可以预分配的序列号个数(默认值:20),设置 nocache 表示不预分配。
create or replace trigger tr_t_test
before insert on t_test
for each row
begin
select t_test_id_seq.nextval into :new.id from dual;
end;
进行上面的设置后,在使用 insert 语句向表 t_test 新增数据后,id 字段就会自动填充数据。
在 Oracle 中可以通过下面 SQL 修改序列的步长:
alter sequence t_test_id_seq increment by 5
但要修改序列初始值就没有这么简单了,需要通过修改步长来解决,若序列 t_test_id_seq 现值是2,需要设置初始值为 100,Increment By 值为 98(100-2)。
alter sequence t_test_id_seq increment by 98;
select t_test_id_seq.nextval from dual;
alter sequence t_test_id_seq increment by 1;
上面的SQL语句中 alter sequence t_test_id_seq increment by 98 将自增步长修改为98,
第二条语句执行select t_test_id_seq.nextval from dual 做一次查询,使初始值增加到100(98+2),最后再自增步长修改回1,这样序列就可以以100为初始值、以自增步长为1进行增长了。
15.4 PostgreSQL 中使用自增字段
在 PostgreSQL 通过使用序列 sequence 来标识字段实现字段的自动增长,序列数据类型有 smallserial、serial 和 bigserial,他们之间主要是数值范围和存储大小的差异。一般使用 serial(数值范围:1 到 2,147,483,647)就可以满足我们日常的需要。以下表格展示了smallserial、serial 和 bigserial 在数据范围和存储大小之间的差异:
结果集:
create table t_test(id serial NOT NULL, name varchar(20))
上面 SQL 语句在 PostgreSQL 中使用 serial 创建了一张以 id 为自增的表,数据库也会自动创建以tablename_id_seq(本例中应为:t_test_id_seq)命名的序列。
现在向表中新增数据,并查询新增的记录:
insert into t_test (name) values('a');
insert into t_test (name) values('b');
select * from t_test
结果集:
新增数据时,数据库为 id 字段自动填充了数据,且初始值为 1,步长为 1。那么在 PostgreSQL 如何修改序列的初始值呢,数据库提供了下面 SQL 语句:
select setval('t_test_id_seq',10,false)
修改序列的初始值为 10 后,再次向表中新增一条记录并查看结果:
insert into t_test (name) values('c');
select * from t_test
结果集:
新增的记录中 id 就会从 10 开始填充,而不是按照原来的顺序填写为 3。值得注意的是修改序列的初始值时,设置值一定要大于当前的最大值,否则会导致向 id 插入重复值而报错。至于修改序列的步长,我们可以通过下面 SQL 语句实现:
alter sequence t_test_id_seq increment by 5
上面语句执行后,序列 t_test_id_seq 的步长变为 5。当我们再向表中添加新记录时,新增的id为15,说明自增步长已经修改为5了。
insert into t_test (name) values('d');
select * from t_test
结果集:
MySQL Oracle SQLServer PostgreSQL 四种数据库以各自独有的方式实现了自增字段的设置,
其中MySQL、SQLServer 和 PostgreSQL 是给列设置属性实现字段的自增,Oracle是通过创建序列并绑定字段来实现字段自增的,虽然复杂但也灵活,可以根据具体需求配置自增初始值和步长。
15.5 小结
尽管自增字段给我们带来了很多方便,比如自增字段为数据库自动生成值,性能较高。由于该字段为数值型,占用空间小,容易创建索引及排序等等。
但自动字段的使用也存在一些缺点,比如当我们准备手动插入特定ID(非数据库自动生成)就比较麻烦,特别是在两张表合并成一张表时,ID之间的重复值处理就显得更不方便。所以在项目中需要结合实际场景综合考虑是否考虑使用自增字段,虽然在大部分场景下还是建议使用的。