Расширяя более ранний комментарий, если вам действительно нужно это сделать и вы не хотите, чтобы в отдельной таблице содержались используемые или доступные значения (что разумно, поскольку в этом есть свои проблемы), вы могли бы добиться этого, если бы моглисоздайте процедуру 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) и проверяет возвращаемое исключение.Принцип тот же - вставьте внутрь цикла, пока не получите ошибку.