【问题标题】:What is the string length of a GUID?GUID 的字符串长度是多少?
【发布时间】:2010-11-01 09:01:40
【问题描述】:

我想在 SQL 中创建一个 varchar 列,该列应包含 N'guid',而 guid 是由 .NET (Guid.NewGuid) 生成的 GUID - 类 System.Guid。

我应该从 GUID 获得的varchar 的长度是多少? 是静态长度吗?

我应该使用nvarchar(GUID 是否会使用 Unicode 字符)?

varchar(Guid.Length)

PS。我不想使用 SQL 行 guid 数据类型。我只是问Guid.MaxLength是什么。

【问题讨论】:

  • 注意:Guid.NewGuid 没有隐含的“字符串长度”;这完全取决于ToString 中使用的格式(无参数ToString 使用“D”格式)。我更喜欢“B”,因为它更容易“看到它是一个 GUID”,但这只是熟悉和约定。
  • 为什么不把它保存为一个 16 字节的唯一标识符?

标签: .net guid varchar sql-types string-length


【解决方案1】:

36,并且 GUID 将只使用 0-9A-F(十六进制!)。

12345678-1234-1234-1234-123456789012

这是任何 GUID 中的 36 个字符——它们的长度是恒定的。您可以阅读更多关于 GUID 的复杂性here

如果要存放大括号,则需要多两个长度。

注意:36 是字符串长度,中间有破折号。它们实际上是 16 字节的数字。

【讨论】:

  • 我认为一个表示围绕着 {},所以这意味着最多 38 个
  • 我很确定你第一次做对了,埃里克。 guid.ToString() 返回一个长度为 36 的字符串,没有大括号。
  • 谢谢你们两个,我需要的是 36,我说我要存储 Guid.NewGuid。
  • 这对 .NET 来说是错误的;你只能得到 36 个字符!您确实获得了 C# 可视化工具的大括号(38 个字符),但不是在代码中!
【解决方案2】:

我相信 GUID 被限制为 16 字节长度(或者 ASCII 十六进制等效项为 32 字节)。

【讨论】:

    【解决方案3】:

    这取决于您如何格式化 Guid:

    • Guid.NewGuid().ToString() => 36 个字符(连字符)
      输出:12345678-1234-1234-1234-123456789abc

    • Guid.NewGuid().ToString("D") => 36 个字符(连字符,与ToString() 相同)
      输出:12345678-1234-1234-1234-123456789abc

    • Guid.NewGuid().ToString("N") => 32 个字符(仅限数字)
      输出:12345678123412341234123456789abc

    • Guid.NewGuid().ToString("B") => 38 个字符(大括号)
      输出:{12345678-1234-1234-1234-123456789abc}

    • Guid.NewGuid().ToString("P") => 38 个字符(括号)
      输出:(12345678-1234-1234-1234-123456789abc)

    • Guid.NewGuid().ToString("X") => 68 个字符(十六进制)
      输出:{0x12345678,0x1234,0x1234,{0x12,0x34,0x12,0x34,0x56,0x78,0x9a,0xbc}}

    【讨论】:

    • @Shimmy - 看第一个'Hypenated,与默认相同'
    • 哦,那是带 H 的“连字符”(我在字典中查找,但找不到连字符)...谢谢
    • 我想补充一点,Guid 是一个 128 位无符号整数。您也可以将其存储为 16 字节数组byte[16]
    • ps,还有另一个选项:Guid.NewGuid().ToString("X") => 68 个字符输出:{0x12345678,0x1234,0x1234,{0x12,0x23,0x12,0x34,0x56 ,0x78,0x9a,0xbc}}
    • 关于带有“N”选项的“仅数字”的评论有点棘手!您应该将其视为没有大括号和连字符
    【解决方案4】:

    正确的做法是将其存储为uniqueidentifier - 然后在数据库中完全可索引等。次佳选择是 binary(16) 列:标准 GUID 的长度正好是 16 个字节。

    如果您必须将其存储为字符串,则长度实际上取决于您选择如何对其进行编码。作为没有连字符的十六进制(AKA base-16 编码),它将是 32 个字符(每个字节两个十六进制数字),所以 char(32)

    但是,您可能想要存储连字符。如果您的空间不足,但您的数据库本身不支持 blob/guid,您可以使用Base64 编码并删除== 填充后缀;这给了你 22 个字符,所以 char(22)。不需要使用 Unicode,也不需要可变长度 - 例如,nvarchar(max) 将是一个糟糕的选择。

    【讨论】:

    • 为什么uniqueidentifer 是完全可索引的但binary(16) 不是?
    【解决方案5】:

    GUID 是 128 位,或者

    0 through ffffffffffffffffffffffffffffffff (hex) or 
    0 through 340282366920938463463374607431768211455 (decimal) or 
    0 through 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 (binary, base 2) or 
    0 through 91"<b.PX48m!wVmVA?1y (base 95)
    

    所以是的,最少 20 个字符长,这实际上浪费了超过 4.25 位,因此您可以使用比 95 更小的基数来提高效率;以 85 为底的最小可能仍然适合 20 个字符:

    0 through -r54lj%NUUO[Hi$c2ym0 (base 85, using 0-9A-Za-z!"#$%&'()*+,- chars)
    

    :-)

    【讨论】:

    • 理论上是的。但是对于今天的巨大硬盘,使用类似 varchar(50) 的东西要实用得多。因此,如果您存储诸如“1234ABC-ABCD-12AB-34CD-FEDCBA12”之类的内容,则不必在翻译时来回转换。您的建议比读取/写入值稍微占用更多 CPU 资源,而这正是您在实践中想要的。
    【解决方案6】:

    22 字节,如果你这样做:

    System.Guid guid = System.Guid.NewGuid();
    byte[] guidbytes = guid.ToByteArray();
    string uuid = Convert.ToBase64String(guidbytes).Trim('=');
    

    【讨论】:

      【解决方案7】:

      二进制字符串存储原始字节数据,而字符串存储文本。在存储SIDGUID 等十六进制值时使用二进制数据。 uniqueidentifier 数据类型包含一个全局唯一标识符或 GUID。这 value 是通过使用 NEWID() 函数派生的,以返回一个对所有对象都是唯一的值。它存储为二进制值,但显示为字符串。

      这是一个例子。

      USE AdventureWorks2008R2;
      GO
      CREATE TABLE MyCcustomerTable
      (
          user_login   varbinary(85) DEFAULT SUSER_SID()
          ,data_value   varbinary(1)
      );
      GO
      
      INSERT MyCustomerTable (data_value)
          VALUES (0x4F);
      GO
      

      适用于:SQL Server 下面的示例使用 uniqueidentifier 数据类型创建 cust 表,并使用 NEWID 用默认值填充表。在分配 NEWID() 的默认值时,每个新的和现有的行都具有 CustomerID 列的唯一值。

      -- Creating a table using NEWID for uniqueidentifier data type.  
      CREATE TABLE cust  
      (  
       CustomerID uniqueidentifier NOT NULL  
         DEFAULT newid(),  
       Company varchar(30) NOT NULL,  
       ContactName varchar(60) NOT NULL,   
       Address varchar(30) NOT NULL,   
       City varchar(30) NOT NULL,  
       StateProvince varchar(10) NULL,  
       PostalCode varchar(10) NOT NULL,   
       CountryRegion varchar(20) NOT NULL,   
       Telephone varchar(15) NOT NULL,  
       Fax varchar(15) NULL  
      );  
      GO  
      -- Inserting 5 rows into cust table.  
      INSERT cust  
      (CustomerID, Company, ContactName, Address, City, StateProvince,   
       PostalCode, CountryRegion, Telephone, Fax)  
      VALUES  
       (NEWID(), 'Wartian Herkku', 'Pirkko Koskitalo', 'Torikatu 38', 'Oulu', NULL,  
       '90110', 'Finland', '981-443655', '981-443655')  
      ,(NEWID(), 'Wellington Importadora', 'Paula Parente', 'Rua do Mercado, 12', 'Resende', 'SP',  
       '08737-363', 'Brasil', '(14) 555-8122', '')  
      ,(NEWID(), 'Cactus Comidas para Ilevar', 'Patricio Simpson', 'Cerrito 333', 'Buenos Aires', NULL,   
       '1010', 'Argentina', '(1) 135-5555', '(1) 135-4892')  
      ,(NEWID(), 'Ernst Handel', 'Roland Mendel', 'Kirchgasse 6', 'Graz', NULL,  
       '8010', 'Austria', '7675-3425', '7675-3426')  
      ,(NEWID(), 'Maison Dewey', 'Catherine Dewey', 'Rue Joseph-Bens 532', 'Bruxelles', NULL,  
       'B-1180', 'Belgium', '(02) 201 24 67', '(02) 201 24 68');  
      GO
      

      【讨论】:

      • 最好使用额外的 ID int identity(1,1) PRIMARY KEY 没有主键的表会招来麻烦。假设您有 100 万客户并且您想要一行 - WHERE CustomerID='xxx' - 您想要扫描整个表还是直接查找?这种双重搜索 - ID=524332 和 CustomerID='xxx' 是一个非常强大的搜索。它既非常快又非常安全(没有人可以用蛮力猜测 GUID)。
      猜你喜欢
      • 1970-01-01
      • 2010-12-16
      • 1970-01-01
      • 1970-01-01
      • 2011-12-01
      • 2012-08-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多