列是Oracle数 据库中一个命名的顺序编号生成器。这个编号生成器能够以串行方式生成一系列的顺序整数。这个特性在数据库开发的过程中,经常会遇到。如果没有这个工具的 话,那么只能够在前台应用程序控制。这不仅会增加应用系统的开发工作量,而且对于并发访问的情况难以控制。如多个用户同时新建一张单据时,就很难保证单据 编号的唯一。故Oracle 数据库的顺序编号生成器是数据库开发工程师的左膀右臂,具有很大的实用价值。具体来说,他可以解决用户的如下几个需求。
需求一:流水号的需求。
在信息化管理系统中,很多地方需要用到流水号。如有些企业物料编码是按照流水号来编写的。原材料按前后顺序用六个数字来表示,每次新建一个后都 递增1。再如一个商场的前台订单管理系统,每张订单的变码原则可能就是按年月日+流水号的方式构成,每张销售订单一个编号。当天的销售订单从 “000001”开始,一张销售订单一个编号,而且编号都是累加1的。而且商场可能有多个收款台,他们分布在商场的不同位置,甚至可能在不同的楼层。因此 如果没有一个自动产生流水号的机制,就需要人工来完成这项工作。很明显这显然是不可能的。虽然也可以通过前台应用程序来控制。但是这也会增加代码的复杂程 度,而且如果要实现多个收款台同时创建销售订单进行统一编号,则基本上不怎么可能。为此通过数据库据的顺序编号生成器来实现这个需求,使最合理的一个方 式。
通过Oracle的序列功能,可以让数据库来自动地生成流水号。而且这个流水号即使在并发行操作下也不会重复,生成的速度比较快、使用方便。
需求二:利用序列当作主键、外键。
在信息化管理系统中,主键外键的应用很普遍。如在一个ERP系统的销售订单中,其订单ID就是一个主键,它唯一的标识了一张销售订单。这个字段 对于终端用户来说没有实际的参考价值。但是对于应用程序或者数据库来说,这个字段则是非常关键的,因为他们就是根据这个ID来唯一的标识销售订单。通常情 况下,只需要保证这个字段唯一即可,随便什么整数都可以。唯一性的要求听起来简单,但是如果要实现手工控制的话,具有一定的难度。最好的情况下,就是让系 统来进行控制。
为此在Oracle数据库中就提出了序列这个功能。数据库管理员如果在数据库设计中,利用序列当作主键。让各个表都使用这个序列产生的整数作为 主键,那么对于数据库的设计、编程、各种主外键关系建立都能够起到意想不到的作用。简单的说,就是序列可以成为数据库中相互独立表之间的黏合剂,把他们组 合成一个统一的表结构。
以上两个只是从用户的角度来考虑序列的作用。那么下面如果成程序员的角度来考虑,会对序列提出哪些具体的要求呢?笔者总结了日常数据库开发过程中大家对序列提出的具体要求以及具体的解决方案,希望能够对大家有所帮助。
要求一:增量以10位单位递增。
通常情况下,序列是以1为单位递增的。如1001、1002、1003等等。但是有些时候,程序员希望这个增量以10(或者以任何一个整数)为 单位递增。如在销售订单订单明细中,其各个项目就是以10为单位进行递增。这主要是为了后续的调整提供方便。不仅如此,在财务管理系统中也都有类似的要 求。那么Oracle数据库的序列能否实现以10为单位或者以任何一个整数为递增单位呢?答案当然是肯定的。在创建序列的时候,默认情况下其递增单位为 1。但是数据库管理员可以利用INCREMENT BY参数指定序列的增量,其默认值为1。如果程序员希望能够实现按10来递增的话,只要把这个参数设置为10即可。
这个参数不仅控制了递增的单位,而且还控制了递增的方向。即按从大到小递减还是按从小到大递增。如这个值设置为10,则其就是按10、20、 30如此递增。如果这个数值设置为-10,其就是按10000(假设最大值为10000)、9990、99980等顺序递减。也就是说如果利用这个字段来 做为表的关键字的话,那么这个关键字可以从大到小生成,也可以从小到大生成。
要求二:设置开始的序列号。
有时候程序员对于序列开始的数字也有额外的要求。如有些是为了序列的为数的统一,如序列号都是10位数等等。但是如果需要号从1开始,就不能够 保证关键字长度的统一。如从1开始到10000,其长度就会长短不一,这对于应用程序取值为造成一定的难度。为此程序员在开发的时候可能会要求所有的关键 字都必须是10位数字。此时就需要指定序列号开始的值。如可以把序列号开始的值设置为1000000001。那么在以后递增的时候,就,能够保证其关键字 都为10位数字。如果不放心的话,可以再设置一个最大值。不过笔者不建议这么做。虽然对于大部分企业来说,这个十位数字已经足够其应用。但是为了保险起 见,还是不要设置最大值为好。虽然不设置最大值可能会造成关键字位数的不统一,但是相比其关键字耗竭超过最大值从而造成应用程序错误来说,这个统一原则还 是可以退一步的。
另外,有时候在流水号编制的时候,可能还需要区分担据的类别。此时也需要管理员指定序列的起始值。如选择有这种情况,企业的销售订单主要分为正 常订单与特价订单,而企业现在销售订单是通过流水号来进行编码。为了区分两种不同的订单情况,在生成流水号的时候有要求。如对于正常的订单,则流水号从 100000到899999;而如果是特价的销售订单,则流水号从900001到999999。每个月周而复始一次。此时,就需要把序列功能跟其他应用结 合。不过主要还是靠序列在发挥作用。为此需要为每种情况设置一个起始值。然数据库自从根据单据类别的不同调用不同的序列。
如果要实现对于起始值的控制,则需要利用参数START WITH。在这后面设置起始值,可以方便用户根据实际情况来设置起始值。笔者以前遇到过一个系统,在这方面设计的很好。这个系统有一个应用字典平台。用户 可以通过这个平台来设置Oracle数据库序列的起始值。而不需要每次调整都从数据库中去调整。这大大提高了程序设计的灵活性。
在设置这个起始值的时候,需要跟上面提到的这个参数挂钩。如果序列是从小到大生成的,则在这里就是要设置其最小值。相反如果序列是从大到小生成 的,则这里设置的就是其最大值。以前有人就在这里犯过一个愚蠢的错误。他设置的时候是让序列从小到大生成的,并且有边界的设置。
是这里初始值设置的时候,则设置了一个最大值。结果这个值还没怎么用系统就报错了。这主要是笔误。为此管理员在设置这个初始值的时候,最好能够再回过头去看看序列的生成模式,是按顺序生成还是倒序生成。
要求三:要确保序列号的连续。
有时候,如在财务凭证编号上,系统要确保这个流水号必须是连续的。此时如果使用这个序列来作为流水号的生成机制的话,那么能否实现所有的序列号都是连续的呢?为了保证实现这个目的,那么就需要设置CACHE参数。
CACHE这个参数主要用来指定在高速缓存中可以预先分配的序列号个数。这是什么意思呢?也就是说,如果这个数字为20的话(默认为20),那 么Oracle一启动的时候就会自动生成20个序列号放在高速缓存中。当应用程序需要使用的时候,就可以马上从高速缓存中拿来使用。从而可以提高应用程序 的性能。当这个20个序列号用完以后,数据库会再生成20个序列号存入到数据库的高速缓存中。很明显,这么设计就是为了提高数据库的性能。可是也会带来一 个副作用。如系统在高速缓存中已经生成了20个序列号(从1991到2010)。而实际上只用了15个(如用到2005)。此时如果数据库因为维护或者其 他原因需要重新启动数据库。此时高速数据缓存中的内容就会丢失。重新启动后Oracle数据库又会生成20个序列号,此时序列号的顺序为2011到 2030。很明显此时2006到2010中间就会断号。为此如果需要保证连号的话,就需要把这个参数设置为Nocache,即不允许预先在高速缓存中生成 序列号。这会降低数据库的性能,但是可以保证序列号的连续性。不会因为数据库重新启动或者其他原因而导致序列号(流水号)断号。