我们可以创建一个给出随机值的 PLSQL 序列吗?

Posted

技术标签:

【中文标题】我们可以创建一个给出随机值的 PLSQL 序列吗?【英文标题】:can we able to create a PLSQL sequence which gives random values? 【发布时间】:2018-12-09 03:21:10 【问题描述】:

我的问题是关于 PL SQL 序列,它需要在起始值和最大值之间给出随机值。我们能做到吗?

【问题讨论】:

到目前为止你尝试了什么? PLSQL generate random integer的可能重复 【参考方案1】:

当然,使用DBMS_RANDOM.VALUE。这是一个简短的概念证明:

set serveroutput on

declare
  x number;
begin
  x := dbms_random.value(3, 9);
  dbms_output.put_line(x);
end;
/

7.77738390408807611656323701045019115674


PL/SQL procedure successfully completed.

你可能想看看整个包:https://docs.oracle.com/database/121/ARPLS/d_random.htm#ARPLS040

【讨论】:

而不是使用 Number.. 尝试 Pls_integer。您将获得数字值。【参考方案2】:

这是一种可能有用的替代方法。它不是完全随机的,因为它基本上所做的只是采用顺序序列号并混淆数字。为了避免像 '100' 和 '1000' 都返回数字 '1' 我在起始值中添加了一个随机数字 1-9。

在直接随机数上这样做的原因是为了避免返回值中的重复/冲突,这将在随机函数中发生。

您当然可以使用 DBMS_RANDOM 方法并针对目标 table.column 值进行检查,以检查该值尚未被使用。

所以,这是我快速而肮脏的随机解决方案:

我还没有彻底测试过。

首先创建一个正常的序列:

CREATE SEQUENCE the_seq START WITH 10000;

现在是随机打乱从序列返回的数字的函数:

CREATE OR REPLACE FUNCTION get_seq_val RETURN NUMBER IS
   l_seq_val   VARCHAR2(50);
   l_ret_val   VARCHAR2(50);
   l_seq_len   NUMBER;
   l_digit     NUMBER;
BEGIN
   SELECT RTRIM(LTRIM(TO_CHAR(the_seq.NEXTVAL))) INTO l_seq_val FROM dual;
   DBMS_OUTPUT.PUT ( 'Seq: ' || l_seq_val );
   l_seq_len := LENGTH(l_seq_val);
   l_ret_val := TRUNC(dbms_random.value(1,9)); -- Avoid having 0 as leading digit below
   DBMS_OUTPUT.PUT ( ' Ret: ' || l_ret_val );
   FOR i IN 1 .. l_seq_len LOOP
      l_digit := TRUNC(dbms_random.value(1, LENGTH(l_seq_val)));
      l_ret_val := l_ret_val || SUBSTR(l_seq_val, l_digit, 1);
      l_seq_val := REGEXP_REPLACE(l_seq_val, '(?<=^.' || l_digit || ')', '' );
      DBMS_OUTPUT.PUT ( ' Dig: ' || l_digit );
      DBMS_OUTPUT.PUT ( ' NowSeq: ' || l_seq_val );
      DBMS_OUTPUT.PUT ( ' Ret: ' || l_ret_val );
   END LOOP;
   DBMS_OUTPUT.PUT_LINE ( ' RETURN: ' || l_ret_val );
   RETURN l_ret_val;
END;
/

show err

现在测试一下:

select rn, get_seq_val() sv from ( select rownum rn from dual connect by level < 20 );

我的输出:

        RN         SV
---------- ----------
         1     801410
         2     610011
         3     140441
         4     514411
         5     341400
         6     341100
         7     801404
         8     301404
         9     310014
        10     800100
        11     615005
        12     510500
        13     850155
        14     205000
        15     201000
        16     705100
        17     550050
        18     411555
        19     615000

19 rows selected.

【讨论】:

以上是关于我们可以创建一个给出随机值的 PLSQL 序列吗?的主要内容,如果未能解决你的问题,请参考以下文章

创建无重复的随机数序列

为啥 Netezza 序列下一个值给出随机值?

PLSQL:2个时间戳之间的随机时间戳

PLSQL 可以从外部共享文件夹中检索文件吗?

我们可以使用表类型参数作为 PLSQL 中的默认空参数吗?

plsql查询中'%%'是模糊查询吗?为啥查不出来呢?