序列sequence:
如果要查employees表中id的最大值
select max(employee_id) from employees;
但是如果要保证主键插入的唯一性的话,如果使用max(employee_id) + 1
的方式是不能避免不重复的,因为可能会遇到并发操作的问题,两个人同时
插入都加了1,结果插入的employee_id重复了
另外一种方式是让主键设为自增列:在oracle中是无法用sql语句实现子增的,
只能通过触发器来实现!
还有一种方式就是序列了:
例:创建一个序列来自动生成序列号
create sequence 序列名
increment by n
start with n
maxvalue n | nomaxvalue
minvalue n | nominvalue
cycle | nocycle
cache n | nocache; 默认缓存20个。
举例说明:
create sequence seq_a
start with 1 默认从1开始
maxvalue 11
increment by 10 ;
这个序列从1到11,每次递增值为10
创建序列后,从中往出取值,取值要用到两个伪列,一个叫做nextval
另外一个叫做currval
select seq_a.currval from dual;
执行失败,任何一个序列的第一次执行必须是nextval不能是currval。
select seq_a.nextval from dual;
第一次执行上述语句是1,第二次执行就是11了。
如果要设置循环的话,cache值必须小于cycle值,注意cache的值必须大于1
alter sequence seq_a
maxvalue 21
cycle
cache 2
更改了序列后
执行select seq_a.nextval from dual;后
显示的是21,在执行相同的语句后,就是1了
,再执行的话是11,再执行就是21,因为设置了循环
所以会从1到21循环的来,每一次都加10。
如果要查看序列的话
输入desc seq就可以
然后,select sequence_name from seq ,可以找到序列名。
这时要往employees表中插入主键的话,不要往主键里面插入记录中没有
出现的值,虽然可以插进去,但这是很危险的,以后会和序列冲突的!!
insert into employees(employee_id,last_name,email,hire_date,
job_id) values(employees_seq.nextval,'aaa','ccc',
sysdate,2,'IT_PROG');
采用主键序列的nextval方式肯定可以保证主键的值不重复而且符合序列,
这时可用
select employees_seq.currval from dual;
可以查出当前的主键序列值,假如是207的话。
注意:插入即便失败了,序列值也会跟着增加的。
假设下面一个人进行了插入主键值为208的操作,但是没有用nextval,再下面
一个人规矩的按照nextval方法插入的话就会出现违反主键唯一性约束的情况。
其实就是直接指明主键插入的话不会更改序列值,除非使用
employees_seq.nextval,
注意插入时如果使用了employees_seq.nextval,不管插入成功与否,
序列都会增加,而且序列值不会受事务回滚的影响!!
事务对sequence是无法恢复的,所以就会出现跳值的现象,就如同子增的跳值
是一样的,实质都一样,子增的实质也是序列,也是不管插入与否,都会子增。
实际数据库中也是无法避免跳数现象的,主键插入就是用nextval方法去作。
注意序列的nextval是完全可以避免并发冲突的,因为里面有并发机制在里面,
不会出现两个人同时nextval,但是取出了相同值的情况。
事务回滚、系统崩溃、两个或多个表共用一个sequence时,会发生序列跳
数的情况。