Как создать случайный уникальный идентификатор длиной от 5 до 10 цифр в оракуле? - PullRequest
0 голосов
/ 19 сентября 2018

Как создать случайный уникальный идентификатор для таблицы длиной от 5 до 10 цифр без использования какой-либо другой таблицы.

Я знаю SYS_GUID и DBMS_RANDOM.value(100000,999999).

В SYS_GUID есть16 символов и DBMS_RANDOM.value(100000,999999) не гарантирует, что next является уникальным, и использует другую таблицу для хранения предыдущего сгенерированного числа, и это не очень хорошая идея.

1 Ответ

0 голосов
/ 19 сентября 2018

Расширяя более ранний комментарий, если вам действительно нужно это сделать и вы не хотите, чтобы в отдельной таблице содержались используемые или доступные значения (что разумно, поскольку в этом есть свои проблемы), вы могли бы добиться этого, если бы моглисоздайте процедуру CRUD для обработки вставки для вас, что-то вроде:

create table t42 (id number, some_col number, constraint pk_t42 primary key (id));

create or replace procedure insert_t42(p_some_col t42.some_col%type) as
begin
  loop
    begin
      -- attempt to insert with a random number
      insert into t42 (id, some_col)
      values (ceil(dbms_random.value(9,99)), p_some_col);
      -- no error, so we are done - exit the loop
      exit;
    exception
      when dup_val_on_index then
        -- random ID already existed; ignore error, will loop again
        null;
        -- debug message just for demo
        dbms_output.put_line('Duplicate ignored');
    end;
  end loop;
end;
/

Цикл будет продолжаться, пока не произойдет случайное значение в требуемом диапазоне, которое не выдает уникальныйнарушение ограничения (dup_val_on_index исключение).Я использовал небольшой диапазон для демонстрации, чтобы сделать возможными конфликты, для 5-10 цифр, которые вы использовали бы ceil(dbms_random.value(9999,9999999999)).

Несмотря на это, вам действительно нужна дополнительная обработка, чтобы предотвратить ее зацикливание, когда все станет доступнобыли использованы значения в этом диапазоне - возможно, со счетчиком, увеличенным в цикле, который выдает свое собственное исключение, когда достигнуто какое-то большое число.Я оставлю это как упражнение ...

В любом случае, чтобы продемонстрировать эту процедуру в действии, этот блок вставляет 50 записей со случайными идентификаторами, выполняя цикл 50 раз и вызывая процедуру один раз за итерацию:

set serveroutput on
begin
  for i in 1..50 loop
    insert_t42(i);
  end loop;
end;
/

Duplicate ignored
Duplicate ignored
Duplicate ignored
Duplicate ignored
Duplicate ignored
Duplicate ignored
Duplicate ignored
Duplicate ignored
Duplicate ignored
Duplicate ignored
Duplicate ignored
Duplicate ignored
Duplicate ignored
Duplicate ignored
Duplicate ignored
Duplicate ignored
Duplicate ignored
Duplicate ignored
Duplicate ignored
Duplicate ignored
Duplicate ignored

PL/SQL procedure successfully completed.

Этот прогон 21 раз попал в исключение dup_val_on_index, но поскольку процедура просто обошла цикл снова, когда это произошло, он все равно вставил 50 уникальных значений:

select * from t42 order by id;

        ID   SOME_COL
---------- ----------
        11         16
        12         46
        14         22
        18         20
        19         44
        22         26
        23         34
        26         36
        27         14
        29         18
        31         39
        32         35
        33         48
        35         19
        36         42
        37         10
        38          5
        39         24
        42         38
        43         50
        49         32
        50         41
        51         12
        52         33
        53         47
        56         21
        57         40
        59         43
        61          8
        63         37
        64         29
        65          1
        67         25
        68         27
        70         49
        73          2
        75         31
        77         13
        78          6
        80          4
        83         30
        87         11
        90          7
        92         23
        93         15
        94          9
        95         17
        96         45
        98          3
        99         28

50 rows selected. 

Вымог бы достичь подобного эффекта без процедуры, если вы выполняете вставку из приложения, либо выполняя анонимный блок с такой же логикой цикла, либо используя собственный цикл Java (или C, или любой другой), который повторяет оператор вставкикак вызов JDBC (или OCI) и проверяет возвращаемое исключение.Принцип тот же - вставьте внутрь цикла, пока не получите ошибку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...