【问题标题】:Generating 6 digit unique random number generator sequence in oracle在 oracle 中生成 6 位唯一随机数生成器序列
【发布时间】:2017-04-07 06:22:58
【问题描述】:

我已经尝试在 oracle SQL 中使用noorder 子句,但我仍然按升序获取生成的序列。

下面是序列创建脚本

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

当我重复运行以下命令时:

select otp_seq.nextval from dual;

它只给出序列中的值:

100000
100001
100002

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

【问题讨论】:

  • 我忘了说我已经从序列中删除了部分 -increment by 1。
  • 创建序列 otp_seq minvalue 100000 maxvalue 999999 nocycle noorder 并且结果仍然正常。
  • 嗯,一个sequence生成sequential值,一个random函数生成random值.但是随机数永远不能保证是唯一的。要么创建一个随机数并在循环中检查它是否已被使用,要么创建带有数字的表并随机选择其中一个然后将其删除(或将其标记为已使用)。
  • 我建议您尝试做的是一个糟糕的设计决策。如果您正在寻找唯一值,为什么它们的生成顺序很重要,顺序还是随机?你想通过这样做来解决什么?验证您的随机数是否唯一会对性能产生影响。

标签: sql oracle sequence


【解决方案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 个值,我认为这不是主要问题。

【讨论】:

    猜你喜欢
    • 2012-12-29
    • 2018-05-03
    • 2013-04-22
    • 1970-01-01
    • 1970-01-01
    • 2013-03-13
    • 1970-01-01
    • 1970-01-01
    • 2019-01-12
    相关资源
    最近更新 更多