从 Oracle 的 RAW(16) 转换为 .NET 的 GUID

Posted

技术标签:

【中文标题】从 Oracle 的 RAW(16) 转换为 .NET 的 GUID【英文标题】:Convert from Oracle's RAW(16) to .NET's GUID 【发布时间】:2011-11-09 12:34:11 【问题描述】:

我在手动调试 Guid 值从 .NET 到 Oracle 不同的 .NET 应用程序时遇到了困难。

C# 的内容如下: 17D89D326C2142D69B989F5201288DBF Oracle 读取: 329DD817216CD6429B989F5201288DBF

我如何能够手动调试,即从 C# 的 GUID 能够将该值粘贴到 oracle 查询中并获得正确的结果(反之亦然)?

【问题讨论】:

Convert byte array from Oracle RAW to System.Guid?的可能重复 为什么我不使用字符串? fml 【参考方案1】:

如果您查看所涉及的(成对的)十六进制数字值,您会发现最后 7 个字节在两种情况下都是相同的,但前 9 个字节稍微切换了一下。

从您的示例开始,但将 .NET 中的每一对重写为 00、11、22 等并切换 Oracle 的相关字节,我们得到:

.NET:

00112233445566778899AABBCCDDEEFF

甲骨文:

33221100554477668899AABBCCFFEEFF

因此编写代码来切换相关字节应该相当容易。 (事实上​​,我很确定我在以前的工作中写了一些代码来做到这一点。)

要切换字节,您只需调用Guid.ToByteArray()new Guid(byte[]) 即可返回Guid

编辑:碰巧,上面的切换轮正是当你传递一个字节数组时Guid构造函数所做的:

using System;
using System.Linq;

class Test

    static void Main()
    
        byte[] bytes = Enumerable.Range(0, 16)
                                 .Select(x => x * 16 + x)
                                 .Select(x => (byte) x)
                                 .ToArray();

        Console.WriteLine(BitConverter.ToString(bytes).Replace("-", ""));
        Console.WriteLine(new Guid(bytes).ToString().Replace("-", ""));
    

打印:

00112233445566778899AABBCCDDEEFF
33221100554477668899aabbccddeeff

这很可能使执行切换变得相当简单...您是如何获得开始时的值的?仅仅是“它们在 Oracle 中的显示方式”吗?

编辑:好的,这里有几个转换函数 - 如果您将数据作为文本,它们会以各种方式转换......

using System;
using System.Linq;

class Test

    static void Main()
    
        string oracle = "329DD817216CD6429B989F5201288DBF";
        string dotNet = "17D89D326C2142D69B989F5201288DBF";

        Console.WriteLine(oracle == DotNetToOracle(dotNet));
        Console.WriteLine(dotNet == OracleToDotNet(oracle));
    

    static string OracleToDotNet(string text)
    
        byte[] bytes = ParseHex(text);
        Guid guid = new Guid(bytes);
        return guid.ToString("N").ToUpperInvariant();
    

    static string DotNetToOracle(string text)
    
        Guid guid = new Guid(text);
        return BitConverter.ToString(guid.ToByteArray()).Replace("-", "");
    

    static byte[] ParseHex(string text)
    
        // Not the most efficient code in the world, but
        // it works...
        byte[] ret = new byte[text.Length / 2];
        for (int i = 0; i < ret.Length; i++)
        
            ret[i] = Convert.ToByte(text.Substring(i * 2, 2), 16);
        
        return ret;
    


【讨论】:

事实证明,不是甲骨文在重新排序。它是 Guid.ToByteArray() 和以字节数组作为参数的 Guid 构造函数。我不知道为什么会这样,我在这里发布了一个问题:***.com/questions/9195551/…【参考方案2】:

在 .NET 中始终使用您的标准 GUID...

当您想在 Oracle 中插入一些 GUID 时,只需调用 Guid.ToString ( "N") 并将该字符串提供给 Oracle(在此示例中,参数名称为 MyNETVAL):

INSERT INTO MyTable ( MyRAWCol)
SELECT HEXTORAW (SUBSTR (MyNETVal, 6, 2) || SUBSTR (MyNETVal, 4, 2) || SUBSTR (MyNETVal, 2, 2) || SUBSTR (MyNETVal, 0, 2) || SUBSTR (MyNETVal, 10, 2) || SUBSTR (MyNETVal, 8, 2) || SUBSTR (MyNETVal, 14, 2) || SUBSTR (MyNETVal, 12, 2) || SUBSTR (MyNETVal, 16, 16)) FROM DUAL;

当您从 Oracle 读取 RAW 时,您使用:

SELECT 
SUBSTR (HexV, 6, 2) || SUBSTR (HexV, 4, 2) || SUBSTR (HexV, 2, 2) || SUBSTR (HexV, 0, 2) || SUBSTR (HexV, 10, 2) || SUBSTR (HexV, 8, 2) || SUBSTR (HexV, 14, 2) || SUBSTR (HexV, 12, 2) || SUBSTR (HexV, 16, 16) AS MyNETVal
FROM (SELECT RAWTOHEX (MyRAWCol) HexV FROM MyTable);

然后您可以将返回的MyNETVal 输入new Guid (MyNETVal)

这样,您的代码始终处理 .NET 格式,并且字节切换发生在 Oracle-DB 中...您不会使用转换代码污染您的代码,并且在切换到其他 DB 时可以保持代码代码相同- 只需更改 SQL 即可启动并运行... SQL 可以使用其他 DB 变得更简单,因为其中一些遵循 Windows 的 GUID 格式...

【讨论】:

这不是 OP 所要求的。如果我知道 .NET 会搞砸 ID,我会立即选择 VARCHAR2。但是现在已经太晚了,现在我需要弄清楚如何匹配它们 你的 subst 差了一个(substr 是基于 1)。 将 RAW 更正为 GUID,因为 SUBSTR 基于 1(不是 0):SELECT SUBSTR (HexV, 7, 2) || SUBSTR (HexV, 5, 2) || SUBSTR (HexV, 3, 2) || SUBSTR (HexV, 1, 2) || SUBSTR (HexV, 11, 2) || SUBSTR (HexV, 9, 2) || SUBSTR (HexV, 15, 2) || SUBSTR (HexV, 13, 2) || SUBSTR (HexV, 17, 16) AS MyNETVal FROM (SELECT RAWTOHEX (MyRAWCol) HexV FROM MyTable);【参考方案3】:

如果您需要将一个GUIDPL/SQL转换为RAW可以使用这个函数:

/*
    CONVERT a GUID FORMAT in RAW(16)
    EX:
        guid    = 88c6a267-65d2-48d6-8da2-6f45e2c22726
        raw     = 67A2C688D265D6488DA26F45E2C22726
*/
FUNCTION GuidToRaw( guid IN VARCHAR2 ) RETURN RAW
IS
    ret         RAW(16);
    guidHex     VARCHAR2(64);
BEGIN

    guidHex := SUBSTR (guid, 7, 2);
    guidHex := CONCAT( guidHex, SUBSTR (guid, 5, 2) );
    guidHex := CONCAT( guidHex, SUBSTR (guid, 3, 2) );
    guidHex := CONCAT( guidHex, SUBSTR (guid, 1, 2) );

    guidHex := CONCAT( guidHex, SUBSTR (guid, 12, 2) );
    guidHex := CONCAT( guidHex, SUBSTR (guid, 10, 2) );

    guidHex := CONCAT( guidHex, SUBSTR (guid, 17, 2) );
    guidHex := CONCAT( guidHex, SUBSTR (guid, 15, 2) );

    guidHex := CONCAT( guidHex, SUBSTR (guid, 20, 2) );
    guidHex := CONCAT( guidHex, SUBSTR (guid, 22, 2) );

    guidHex := CONCAT( guidHex, SUBSTR (guid, 25, 12) );

    ret := HEXTORAW( guidHex );

    return ret;

end;

【讨论】:

【参考方案4】:

我在从 Oracle 存储和读取 Guid 时遇到了同样的问题。

Jon 的回答对于查询是正确的,但如果您的应用需要从 Oracle 存储和读取 Guid,请使用该线程中的 FlipEndian 函数:

.NET Native GUID conversion

Byte[] rawBytesFromOracle;
Guid dotNetGuid = new Guid(rawBytesFromOracle).FlipEndian();

只有在从 Oracle 回读时才需要翻转。

写入 Oracle 时,正常使用 Guid.ToByteArray()。

我花了太多时间试图完成这个简单的任务。

史蒂夫

【讨论】:

以上是关于从 Oracle 的 RAW(16) 转换为 .NET 的 GUID的主要内容,如果未能解决你的问题,请参考以下文章

Oracle raw类型

oracle中如何实现blob和base64相互转换

如何在 Swift 中将数值数据数组转换为 RAW 图像数据?

将小型 Oracle 长原始值转换为其他类型

linux下ORACLE之RAW创建

将 oracle 转换为 PostgreSQL 时出现数字溢出