如何在不使用任何其他表的情况下为5到10位数字的表生成随机唯一ID。
我认识SYS_GUID
和DBMS_RANDOM.value(100000,999999)
。
SYS_GUID
中的字符为16个字符,DBMS_RANDOM.value(100000,999999)
不保证next是唯一的,它使用另一个表来存储先前生成的数字,这不是一个好主意。
答案 0 :(得分:1)
在前面的评论中进行扩展,如果您确实需要执行此操作,并且不想让一个单独的表保存已使用或可用的值(这是合理的,因为这有其自身的问题),则可以实现此目的创建一个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
异常)。我在演示中使用了一个很小的范围来产生冲突,您可能会使用ceil(dbms_random.value(9999,9999999999))
来表示5-10位数字。
即便如此,一旦使用了该范围内的所有可用值,您确实确实需要进一步处理以防止其永远循环-可能在循环中增加一个计数器,当达到某个大数字时,该计数器将引发其自身的异常。我将其保留为练习...
无论如何,为了演示该过程的实际效果,该块通过循环50次并在每次迭代中调用一次过程来插入带有随机ID的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.
该运行遇到dup_val_on_index
异常21次,但是由于该过程在发生该异常时再次循环,因此它仍然插入了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)调用重复,并检查是否返回异常。原理是相同的-插入循环中,直到没有错误为止。