5

我的应用程序内部使用通过 sys_guid() 生成的 RAW(16) guid。
最近我开始关联 Active Directory 用户,我在其中获得 guid,格式为:00000000-0000-0000-0000-00000000000

以下两个函数是否正确执行此转换?

找到以下网站:

http://www.timvasil.com/blog14/post/2009/01/20/User-defined-function-to-convert-from-RAW(16)-to-a-GUID-in-Oracle.aspx

create or replace
FUNCTION RAWTOGUID
( RawData IN RAW
) RETURN VARCHAR AS

BEGIN

declare HexData varchar(32) := rawtohex(RawData);

begin
return
    substr(HexData, 7, 2) 
    || substr(HexData, 5, 2) 
    || substr(HexData, 3, 2) 
    || substr(HexData, 1, 2) 
    || '-'
    || substr(HexData, 11, 2) 
    || substr(HexData, 9, 2) 
    || '-'
    || substr(HexData, 15, 2) 
    || substr(HexData, 13, 2) 
    || '-'
    || substr(HexData, 17, 4) 
    || '-'
    || substr(HexData, 21, 12);
end;

END RAWTOGUID;

在以下站点中添加:

http://dbaspot.com/oracle-server/69226-guid-char-conversion-function.html

想出了这个函数来做相反的事情:

create or replace
FUNCTION GUIDTORAW
( HexData IN VARCHAR
) RETURN RAW AS

BEGIN

declare StringData varchar(32) := TRANSLATE(HexData,'0{-}','0');

begin

return
    hextoraw(substr(StringData, 7, 2) 
    || substr(StringData, 5, 2) 
    || substr(StringData, 3, 2) 
    || substr(StringData, 1, 2)
    || substr(StringData, 11, 2) 
    || substr(StringData, 9, 2) 
    || substr(StringData, 15, 2) 
    || substr(StringData, 13, 2)
    || substr(StringData, 17, 4)
    || substr(StringData, 21, 12));
end;

END GUIDTORAW;

他们来回转换,但我真的尊重字节序还是有正确的顺序?

4

1 回答 1

6

引用UUID 标准

UUID 的结构是:

   字段数据类型八位字节注释
                                        #

   time_low unsigned 32 0-3
                          位整数时间戳

   time_mid unsigned 16 4-5 中间字段
                          位整数时间戳

   time_hi_and_version unsigned 16 6-7 高场
                          位整数时间戳复用
                                               带有版本号

   clock_seq_hi_and_rese unsigned 8 8 的高场
   rved 位整数时钟序列
                                               与多路复用
                                               变体

   clock_seq_low unsigned 8 9 的低场
                          位整数时钟序列

   node unsigned 48 10-15 空间唯一性
                          位整数节点标识符

相反,在没有明确的应用程序或表示协议规范的情况下,UUID 被编码为 128 位对象,如下所示:

这些字段被编码为 16 个八位字节,具有上面定义的字段的大小和顺序,并且每个字段首先以最高有效字节编码(称为网络字节顺序)。请注意,字段名称(尤其是多路复用字段)遵循历史惯例。

   0 1 2 3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- +-+-+-+-+-+-+-+
   | 时间_低 |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- +-+-+-+-+-+-+-+
   | time_mid | time_hi_and_version |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- +-+-+-+-+-+-+-+
   |clk_seq_hi_res | clk_seq_low | 节点 (0-1) |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- +-+-+-+-+-+-+-+
   | 节点 (2-5) |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- +-+-+-+-+-+-+-+

引用Guid 文档

public Guid(int a, short b, short c, byte[] d)

Guid(1,2,3,new byte[]{0,1,2,3,4,5,6,7})
creates a Guid that corresponds to "00000001-0002-0003-0001-020304050607".

根据Wikipedia's Endianness 文章, Windows 以 little endian --> 最低有效字节优先存储数字

映射 1,2,3,new byte[]{0,1,2,3,4,5,6,7} 到“00000001-0002-0003-0001-020304050607”,显示数字显示得很大-endian,与 UUID 标准一样,但是,字节数组以与显示相同的顺序提供 - 无需交换字节。

所以Guids显示为:

{time_low (4B) - time_mid (2B) - time_hi_and_version (2B) - clock_sq_hi_and_reserved(1B), clock_seq_low (1B) - 节点 (6B)}

在 little endian 中,这会导致字节顺序(byte[] 不计为数字,因此:

{3,2,1,0 - 5,4 - 7,6 - 8,9 - 10,11,12,13,14,15}

这导致十六进制字符顺序(每个字节是 2 个十六进制数字):

{6,7,4,5,2,3,0,1 - 10,11,8,9 - 14,15,12,13 - 16,17,18,19 - 20,21,22,23,24 ,25,26,27,28,29,30,31}

在 Oracle 中,substr 字符串函数是从 1 开始的,因此 Oracle 字符串索引是:

{7,8,5,6,3,4,1,2 - 11,12,9,10 - 15,16,13,14 - 17,18,19,20 - 21,22,23,24,25 ,26,27,28,29,30,31,32}

这导致命令

substr(HexData, 7, 2) 
|| substr(HexData, 5, 2) 
|| substr(HexData, 3, 2) 
|| substr(HexData, 1, 2) 
|| '-'
|| substr(HexData, 11, 2) 
|| substr(HexData, 9, 2) 
|| '-'
|| substr(HexData, 15, 2) 
|| substr(HexData, 13, 2) 
|| '-'
|| substr(HexData, 17, 4) 
|| '-'
|| substr(HexData, 21, 12);

并转置(删除'-'后):

{7,8,5,6,3,4,1,2, 11,12,9,10, 15,16,13,14, 17,18,19,20, 21,22,23,24,25 ,26,27,28,29,30,31,32}

被反转回

{1,2,3,4,5,6,7,8, 9,10,11,12, 13,14,15,16, 17,18,19,20, 21,22,23,24,25 ,26,27,28,29,30,31,32}

使用相同的函数(不添加“-”) - 将 BE 转换为 LE 并将 LE 转换为 BE 具有相同的交换,因为字节只是简单地反转,而反转反转的字节会导致不反转的字节。

于 2013-03-04T17:30:47.840 回答