2017-04-07 137 views
1

我曾尝试在oracle SQL中使用noorder子句,但仍然按升序获取生成的序列。在oracle中生成6位唯一的随机数生成器序列

下面是序列创建脚本

create sequence otp_seq 
    minvalue 100000 maxvalue 999999 
    increment by 1 nocycle noorder; 

当我运行下面的命令多次:

select otp_seq.nextval from dual; 

它仅给出了在序列中的值:

100000 
100001 
100002 

我想要从给定的域中随机生成值,即minValue和maxValue之间的值应该是唯一的

+0

我忘了提及我已经删除部分增量1之间的序列。 – ankit

+0

创建序列otp_seq minvalue 100000 maxvalue 999999 nocycle noorder 仍然结果是有序的。 – ankit

+0

好吧,*序列*产生*顺序* vaues,*随机*函数产生*随机*值。但是一个随机数永远不能保证是唯一的。要么创建一个随机数,并在循环中检查它是否已被使用,或者创建包含数字的表并随机选择其中的一个,然后删除它(或将其标记为已使用)。 – dnoeth

回答

1

关于NOORDER条款,the documentation says

“指定NOORDER如果你不想要保证序号是对的请求顺序产生。”

的关键词是保证NOORDER不承诺随机性,这意味着NEXTVAL可能会乱序产生数字。这在RAC环境中主要关注,其中每个节点都有一个序列号缓存;在这些情况下NOORDER意味着我们不能从给定值的序列推断NEXTVAL请求的序列,即我们不能使用这些数字按创建顺序对记录进行排序。

根据您的要求。

您的要求是矛盾的。随机性意味着不可预测性。唯一性意味着可预测性。

你不能用一个序列实现这一点,但你可以建立你喜欢这个自己的事情:

create table pseudo_sequence (
    used varchar2(1) default 'N' not null 
    , id number not null 
    , next_val number not null 
    , primary key (used, id) 
    ) 
organization index 
/

注意索引表只有语法。下一个技巧是随机填充表格。

insert into pseudo_sequence (id, next_val) 
with nbr as (
    select level + 99999 as nx 
    from dual 
    connect by level <= 900000 
    order by dbms_random.value 
) 
select rownum, nx from nbr 
/ 

我们需要ID列来保留整个表的NEXT_VAL的随机分布;如果没有它,索引会强制执行一个命令,并且我们希望避免每次执行查询时进行排序。

下一步,我们建立一个查询来获取从表中的下一个值,并将其标记为使用:

create or replace function random_nextval 
    return number 
is 
    pragma autonomous_transaction; 
    cursor ps is 
     select next_val 
     from pseudo_sequence 
     where used = 'N' 
     and rownum = 1 
     for update of used skip locked; 
    return_value number; 
begin 
    open ps; 
    fetch ps into return_value; 
    update pseudo_sequence 
    set used = 'Y' 
    where current of ps; 
    close ps; 
    commit; 
    return return_value; 
end; 
/

,这里是它如何工作的:

SQL> select random_nextval from dual 
    2 connect by level <= 5 
    3/ 

RANDOM_NEXTVAL 
-------------- 
     216000 
     625803 
     806843 
     997165 
     989896 

SQL> select * from pseudo_sequence where used='Y' 
    2/

U   ID NEXT_VAL 
- ---------- ---------- 
Y   1  216000 
Y   2  625803 
Y   3  806843 
Y   4  997165 
Y   5  989896 

SQL> select random_nextval from dual 
    2 connect by level <= 5 
    3/

RANDOM_NEXTVAL 
-------------- 
     346547 
     911900 
     392290 
     712611 
     760088 

SQL> 

当然,我们可以认为这不是随机的,因为通过查看底层表可以预测下一个值,但也许它足够满足您的需求。我不会对多用户环境中的可伸缩性做出任何承诺,但考虑到您的数字空间仅有900,000个值,我认为这不是一个主要问题。

+0

谢谢APC。 立即解决了问题。 – ankit