Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 为什么dbms_random.value在图形查询(连接方式)中返回相同的值?_Sql_Oracle_Random - Fatal编程技术网

Sql 为什么dbms_random.value在图形查询(连接方式)中返回相同的值?

Sql 为什么dbms_random.value在图形查询(连接方式)中返回相同的值?,sql,oracle,random,Sql,Oracle,Random,在Oracle 11.2.0.4.0上,当我运行以下查询时,每一行都会得到不同的结果: select r.n from ( select trunc(dbms_random.value(1, 100)) n from dual ) r connect by level < 100; -- returns random values 是否可以使第二个查询为每行返回随机值 使现代化 我的例子可能过于简化了,下面是我要做的: with reservations(val) as ( se

在Oracle 11.2.0.4.0上,当我运行以下查询时,每一行都会得到不同的结果:

select r.n from (
  select trunc(dbms_random.value(1, 100)) n from dual
) r
connect by level < 100; -- returns random values
是否可以使第二个查询为每行返回随机值

使现代化 我的例子可能过于简化了,下面是我要做的:

with reservations(val) as (
  select 1 from dual union all
  select 3 from dual union all
  select 4 from dual union all
  select 5 from dual union all
  select 8 from dual
)
select * from (
  select rnd.val, CONNECT_BY_ISLEAF leaf from (
    select trunc(dbms_random.value(1, 10)) val from dual
  ) rnd
  left outer join reservations res on res.val = rnd.val
  connect by res.val is not null
)
where leaf = 1;
但预订量可以从1到1.000.000.000甚至更多。
有时,如果该查询立即选择了一个没有保留的随机值,或者由于总是使用相同的dbms_random.value值进行尝试而出现内存不足错误,则该查询将正确返回。

您可以在子查询中移动connect by子句:

select r.n, (select r.n from dual) from (
  select trunc(dbms_random.value(1, 100)) n from dual
  connect by level < 100
) r;

         N (SELECTR.NFROMDUAL)
---------- -------------------
        90                  90
        69                  69
        15                  15
        53                  53
         8                   8
         3                   3
...
我试图做的是生成一个随机数序列,然后找到第一个在某个表中没有记录的随机数

您可能会执行以下操作:

select r.n
from (
  select trunc(dbms_random.value(1, 100)) n from dual
  connect by level < 100
) r
where not exists (
  select id from your_table where id = r.n
)
and rownum = 1;
但它会在检查任何一个随机值之前生成所有100个随机值,这有点浪费;由于您可能在这100个电话中找不到差距,并且在这100个电话中可能有重复的电话,因此您可能需要更大的范围,这也很昂贵,尽管不需要这么多随机电话:

select min(r.n) over (order by dbms_random.value) as n
from (
  select level n from dual
  connect by level < 100 -- or entire range of possible values
) r
where not exists (
  select id from your_table where id = r.n
)
and rownum = 1;
或者重复一次检查,直到找到匹配项

另一种方法是有一个包含所有可能ID的查找表,其中有一列指示它们是使用的还是免费的,可能还有一个位图索引;然后用它来找到第一个或任何随机的自由值。但是,您也必须维护该表,并在使用和释放主表中的ID时进行原子更新,这意味着使事情变得更加复杂并序列化访问—尽管如果您不想使用序列,您可能无法避免这种情况。你可能会用一种物质化的观点来简化事情

如果你有一个相对较少的间隙,并且你真的想重用这些间隙,那么你可能只能搜索指定范围内的间隙,如果没有间隙,那么就返回到序列器。假设您当前使用的值仅在1到1000之间,缺少一些值;您可以在1-100范围内寻找一个自由值,如果没有,则使用序列获取1001,而不是始终在间隙搜索中包含整个可能的值范围。这也将填补优先于扩大使用范围的空白,这可能有用,也可能无用。我不确定我是否不需要这些数字是连续的,也就是说它们不应该是连续的,或者这不重要


除非您特别需要填补空白,并且分配的值不是连续的,否则我只使用序列并忽略空白。

我通过以下查询获得了正确的结果,但我不确定这种方法是否真的可取:

with
  reservations(val) as (
    select 1 from dual union all
    select 3 from dual union all
    select 4 from dual union all
    select 5 from dual union all
    select 8 from dual
  ),
  rand(v) as (
    select trunc(dbms_random.value(1, 10)) from dual
  ),
  next_res(v, ok) as (
    select v, case when exists (select 1 from reservations r where r.val = rand.v) then 0 else 1 end from rand
  ),
  recursive(i, v, ok) AS (
    select 0, 0, 0 from dual
    union all
    select i + 1, next_res.v, next_res.ok from recursive, next_res where i < 100 /*maxtries*/ and recursive.ok = 0
)
select v from recursive where ok = 1;

你的评论…我想避免并发问题让我思考


为什么不尝试插入一个随机数,注意重复的违规行为,然后重试直到成功?即使是查找可用数字的非常聪明的解决方案,也可能在两个单独的会话中产生相同的新数字。因此,只有插入并提交的预订号码是安全的。

可能重复@user7294900不,我不相信这些情况是相同的。嗯,我可能过度简化了我的示例:我尝试生成一个随机数序列,并找到第一个在某个相关表中没有记录的随机数,这样我就不会在级别上真正使用连接条件。例如,我可以从1到1.000.000.000进行预订,我想查找当前未使用的预订号码。我不使用序列,因为我不需要这些数字是连续的,它们可以在一段时间后重用,我希望避免并发问题。这可以简化很多事情。
with
  reservations(val) as (
    select 1 from dual union all
    select 3 from dual union all
    select 4 from dual union all
    select 5 from dual union all
    select 8 from dual
  ),
  rand(v) as (
    select trunc(dbms_random.value(1, 10)) from dual
  ),
  next_res(v, ok) as (
    select v, case when exists (select 1 from reservations r where r.val = rand.v) then 0 else 1 end from rand
  ),
  recursive(i, v, ok) AS (
    select 0, 0, 0 from dual
    union all
    select i + 1, next_res.v, next_res.ok from recursive, next_res where i < 100 /*maxtries*/ and recursive.ok = 0
)
select v from recursive where ok = 1;