这篇博客解释说,sys_guid()每个系统的输出都不是随机的:
http://feuerthoughts.blogspot.de/2006/02/watch-out-for-sequential-oracle-guids.html
不幸的是我必须使用这样的系统.
如何确保获得随机UUID?有可能sys_guid()吗?如果不是如何在Oracle上可靠地获取随机UUID?
Jon*_*ler 26
这是一个完整的例子,基于@Pablo Santa Cruz的答案和你发布的代码.
我不确定你为什么收到错误信息.这可能是SQL Developer的一个问题.在SQL*Plus中运行它时,一切正常,并添加一个函数:
create or replace and compile
java source named "RandomUUID"
as
public class RandomUUID
{
public static String create()
{
return java.util.UUID.randomUUID().toString();
}
}
/
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)Java created.
CREATE OR REPLACE FUNCTION RandomUUID
RETURN VARCHAR2
AS LANGUAGE JAVA
NAME 'RandomUUID.create() return java.lang.String';
/
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)Function created.
select randomUUID() from dual;
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)RANDOMUUID() -------------------------------------------------------------- 4d3c8bdd-5379-4aeb-bc56-fcb01eb7cc33
但SYS_GUID如果可能的话,我会坚持下去.查看My Oracle Support上的ID 1371805.1 - 该错误应该在11.2.0.3中修复.
编辑
哪一个更快取决于功能的使用方式.
在SQL中使用时,Java版本看起来稍快一些.但是,如果您要在PL/SQL上下文中使用此函数,则PL/SQL函数的速度大约是其两倍.(可能是因为它避免了引擎之间切换的开销.)
这是一个简单的例子:
--Create simple table
create table test1(a number);
insert into test1 select level from dual connect by level <= 100000;
commit;
--SQL Context: Java function is slightly faster
--
--PL/SQL: 2.979, 2.979, 2.964 seconds
--Java: 2.48, 2.465, 2.481 seconds
select count(*)
from test1
--where to_char(a) > random_uuid() --PL/SQL
where to_char(a) > RandomUUID() --Java
;
--PL/SQL Context: PL/SQL function is about twice as fast
--
--PL/SQL: 0.234, 0.218, 0.234
--Java: 0.52, 0.515, 0.53
declare
v_test1 raw(30);
v_test2 varchar2(36);
begin
for i in 1 .. 10000 loop
--v_test1 := random_uuid; --PL/SQL
v_test2 := RandomUUID; --Java
end loop;
end;
/
Run Code Online (Sandbox Code Playgroud)
版本4 GUID不是完全随机的.一些字节应该是固定的.我不确定为什么要这样做,或者它是否重要,但根据https://www.cryptosys.net/pki/uuid-rfc4122.html:
生成版本4 UUID的过程如下:
Run Code Online (Sandbox Code Playgroud)Generate 16 random bytes (=128 bits) Adjust certain bits according to RFC 4122 section 4.4 as follows: set the four most significant bits of the 7th byte to 0100'B, so the high nibble is "4" set the two most significant bits of the 9th byte to 10'B, so the high nibble will be one of "8", "9", "A", or "B". Encode the adjusted bytes as 32 hexadecimal digits Add four hyphen "-" characters to obtain blocks of 8, 4, 4, 4 and 12 hex digits Output the resulting 36-character string "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
Java版本的值似乎符合标准.
小智 15
以下函数使用sys_guid()并将其转换为uuid格式:
create or replace function random_uuid return VARCHAR2 is
v_uuid VARCHAR2(40);
begin
select regexp_replace(rawtohex(sys_guid()), '([A-F0-9]{8})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{12})', '\1-\2-\3-\4-\5') into v_uuid from dual;
return v_uuid;
end random_uuid;
Run Code Online (Sandbox Code Playgroud)
它不需要创建dbms_crypto包并授予它.
我现在使用它作为一种解决方法:
create or replace function random_uuid return RAW is v_uuid RAW(16); begin v_uuid := sys.dbms_crypto.randombytes(16); return (utl_raw.overlay(utl_raw.bit_or(utl_raw.bit_and(utl_raw.substr(v_uuid, 7, 1), '0F'), '40'), v_uuid, 7)); end random_uuid;
该功能需要dbms_crypto和utl_raw.两者都需要执行授权.
grant execute on sys.dbms_crypto to uuid_user;
Run Code Online (Sandbox Code Playgroud)
对我来说获得基于 Java 的函数的最简单、最短的方法是:
create or replace function random_uuid return varchar2 as
language java
name 'java.util.UUID.randomUUID() return String';
Run Code Online (Sandbox Code Playgroud)
我无法完全理解为什么如果我添加它就无法编译.toString()。