How to generate a version 4 (random) UUID on Oracle?

前端 未结 9 1102
野性不改
野性不改 2020-12-05 10:37

This blog explains, that the output of sys_guid() is not random for every system:

http://feuerthoughts.blogspot.de/2006/02/watch-out-for-sequential-orac

9条回答
  •  暗喜
    暗喜 (楼主)
    2020-12-05 11:30

    According to UUID Version 4 format should be xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx. @lonecat answer provide this format, also @ceving answer partially provide version 4 requirements. Missing part is format y, y should be one of 8, 9, a, or b.

    After mixing these answers and fix the y part, code looks like below:

    create or replace function fn_uuid return varchar2 is
      /* UUID Version 4 must be formatted as xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx where x is any hexadecimal character (lower case only) and y is one of 8, 9, a, or b.*/
    
      v_uuid_raw raw(16);
      v_uuid     varchar2(36);
      v_y        varchar2(1);
    begin
    
      v_uuid_raw := sys.dbms_crypto.randombytes(16);
      v_uuid_raw := utl_raw.overlay(utl_raw.bit_or(utl_raw.bit_and(utl_raw.substr(v_uuid_raw, 7, 1), '0F'), '40'), v_uuid_raw, 7);
    
      v_y := case round(dbms_random.value(1, 4))
                when 1 then
                 '8'
                when 2 then
                 '9'
                when 3 then
                 'a'
                when 4 then
                 'b'
               end;
    
      v_uuid_raw := utl_raw.overlay(utl_raw.bit_or(utl_raw.bit_and(utl_raw.substr(v_uuid_raw, 9, 1), '0F'), v_y || '0'), v_uuid_raw, 9);
      v_uuid     := regexp_replace(lower(v_uuid_raw), '([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');
    
      return v_uuid;
    end fn_uuid;
    

提交回复
热议问题