oracle 9i数据库表
合同信息表(contract_info):字段:
合同ID:contract_id,number型主键,序列生成,递增
合同编号-contract_code nvarchar2(20),格式如XXXX0001,其中XXXX表示n位大写英文字母,0001顺序编号,合同号有唯一约束简单描述下合同号生成规则:
流程开始时,contract_info表中存在记录,但记录的contract_code字段为空,
流程进行到特定节点时,要生成合同号,并把生成的合同号根据contract_id,更新到对应的contract_code字段.生成合同号时,XXXX已知,根据XXXX到contract_info中查找表中已有的合同号的前n位字母也是XXXX,且序号最大的记录
获得后边的序号,然后+1后生成新的四位序号,XXXX与新序号拼接,生成新的合同号,此合同号更新到contract_code字段。
这个合同号的更新过程使用存储过程实现存在一个问题,如果表中有两条合同号为空的记录,这两条记录生成合同号时,由于业务规则相同,其前边的n位英文大写字母即XXXX相同,由于操作业务的人较多,可能同时要查询表中已有的、前n位字母也是XXXX的合同号以获得后四位序号,此时这两条记录生成的合同号可能完全是一样的,而根据业务规则,这是不允许的。怎样才能避免这个问题,需要在存储过程中对表或行加锁吗?
加锁的话如何加?最好能有个差不多的例子,100分感谢!
合同信息表(contract_info):字段:
合同ID:contract_id,number型主键,序列生成,递增
合同编号-contract_code nvarchar2(20),格式如XXXX0001,其中XXXX表示n位大写英文字母,0001顺序编号,合同号有唯一约束简单描述下合同号生成规则:
流程开始时,contract_info表中存在记录,但记录的contract_code字段为空,
流程进行到特定节点时,要生成合同号,并把生成的合同号根据contract_id,更新到对应的contract_code字段.生成合同号时,XXXX已知,根据XXXX到contract_info中查找表中已有的合同号的前n位字母也是XXXX,且序号最大的记录
获得后边的序号,然后+1后生成新的四位序号,XXXX与新序号拼接,生成新的合同号,此合同号更新到contract_code字段。
这个合同号的更新过程使用存储过程实现存在一个问题,如果表中有两条合同号为空的记录,这两条记录生成合同号时,由于业务规则相同,其前边的n位英文大写字母即XXXX相同,由于操作业务的人较多,可能同时要查询表中已有的、前n位字母也是XXXX的合同号以获得后四位序号,此时这两条记录生成的合同号可能完全是一样的,而根据业务规则,这是不允许的。怎样才能避免这个问题,需要在存储过程中对表或行加锁吗?
加锁的话如何加?最好能有个差不多的例子,100分感谢!
只要没有中间插入记录就可以了
基本上是一个主键生成策略的问题。
这种生成方式在并发访问时不适用。如果号码非要连续的话,等待高手吧。
如果不需要连续,推荐你使用一个序列sequence,使用.nextval来获得下一个值,这样能保证不重复。
然后排序,顺序肯定是确定的,所以rownum肯定也是确定的,再全部update一下
就可以变成AAA0001, AAA0002, AAA0003
不行的话只能锁表,可以用select * from table for update
例如
create table t_seq
(
sqe_name varchar2(20),
curvalue number
)
;
使用的时候
update t_seq
set curvalue = curvalue +1
where sqe_name='XXXX'
returnning into v_value;
这样就确保不会出问题了
例如
create table t_seq
(
sqe_name varchar2(20),
curvalue number
)
;使用的时候
update t_seq
set curvalue = curvalue +1
where sqe_name='XXXX'
returning curvalue into v_value;这样就确保不会出问题了
即使前边的n位英文大写字母即XXXX相同,但不是同一个contract_id。这样就可以避免LZ的问题了吧。
顺嘴胡说,仅供LZ参考
将contract_code这列加上个条件, 不准重复! 不就可以了吗? 如果出现你说的问题: 2个客服人员生成了2个一样的“编号”,那么他们更新表的时候,只有最前面的一条数据能更新成功,重复的数据 在存储过程中 exception中处理!
这样可以吧,给点分吧 LZ,谢谢!
至于如何用Java开发Oracle存储过程,请见:http://www.developer.com/db/article.php/3337411
lockhandle varchar2(200);
ln number;
begin
dbms_lock.allocate_unique('MyLock', lockhandle);
ln := dbms_lock.request(lockhandle,timeout => 0);
if ln not in (0, 4) then
dbms_output.put_line('Already run...');
return;
end if;
dbms_lock.sleep(10);
ln := dbms_lock.release(lockhandle);
exception
when others then
ln := dbms_lock.release(lockhandle);
raise;
end;
用Java开发Oracle存储过程如果想满足17L的要求,我觉得用Java存储过程(其中的方法用Synchronized约束)就可以了。