5

私のアプリは、sys_guid() によって生成された RAW(16) GUID を内部的に使用します。
最近、00000000-0000-0000-0000-00000000000 の形式で GUID を取得する Active Directory ユーザーの関連付けを開始しました。

次の 2 つの関数は、この変換を正しく行っていますか?

次のサイトを見つけました。

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_low |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- +-+-+-+-+-+-+-+
   | | 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".

ウィキペディアのエンディアンに関する記事によると、Windows は数値をリトル エンディアンで保存します --> 最下位バイトが最初です。

1,2,3,new byte[]{0,1,2,3,4,5,6,7} を "00000001-0002-0003-0001-020304050607" にマッピングすると、数値が大きく表示されることがわかります-endian、ただし、UUID 標準と同様に、バイト配列は表示と同じ順序で提供されます。バイトを交換する必要はありません。

したがって、ガイドは次のように表示されます。

{time_low (4B) - time_mid (2B) - time_hi_and_version (2B) - clock_sq_hi_and_reserved (1B), clock_seq_low (1B) - ノード (6B)}

リトル エンディアンでは、これはバイト オーダーになります (byte[] は数値としてカウントされないため、次のようになります。

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

16 進数の文字順になります (各バイトは 2 桁の 16 進数です)。

{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 に答える