GUID的字符串长度是多少?

466

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

从GUID中可以期望得到什么长度的varchar?这是一个静态长度吗?

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

varchar(Guid.Length)

顺便说一下,我不想使用SQL行GUID数据类型。我只是想知道Guid.MaxLength是什么。


1
注意:Guid.NewGuid 没有隐含的“字符串长度”;它取决于在 ToString 中使用的格式(无参数的 ToString 使用 “D” 格式)。我更喜欢使用 “B”,因为这样更容易“看出它是一个 GUID”,但这只是熟悉和惯例。 - user166390
11
为什么不将它保存为一个16字节的唯一标识符? - Filip Cornelissen
7个回答

997
这取决于你如何格式化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}}


3
好的,那么正确的拼写是“Hyphen”,带有一个H(我在词典中查找时未能找到“hypen”)...谢谢。 - Shimmy Weitzhandler
36
我可以帮助您翻译这段内容。 "我想补充一下,Guid 是一个 128 位无符号整数。您也可以将其存储为一个 16 字节的数组 byte[16]。" - Eric Falsken
4
ps,还有另一种选择: Guid.NewGuid().ToString("X") => 68个字符 输出:{0x12345678,0x1234,0x1234,{0x12,0x23,0x12,0x34,0x56,0x78,0x9a,0xbc}}另一种选项是: Guid.NewGuid().ToString("X") => 68个字符 输出为:{0x12345678,0x1234,0x1234,{0x12,0x23,0x12,0x34,0x56,0x78,0x9a,0xbc}}。 - Filip Cornelissen
1
.NET 格式参考页面:http://msdn.microsoft.com/zh-cn/library/97af8hh4.aspx - Patrick M
7
关于“仅数字”和“N”选项的评论有一些棘手!你应该将其解读为没有括号和连字符。 - Jowen
显示剩余7条评论

78

36个字符,GUID仅使用0-9A-F(十六进制)!

12345678-1234-1234-1234-123456789012

任何GUID都是36个字符的长度。 如果您想存储大括号,则需要两个额外的长度。

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

您可以在这里阅读有关GUID的详细信息。


2
我认为一个表示用{}括起来,这意味着最多38个。 - Mitch Wheat
4
我很确定你第一次就做对了,Eric。guid.ToString()返回长度为36的字符串,没有括号。 - Michael Petrotta
1
谢谢你们两个,我需要的是36,我说我想要存储Guid.NewGuid。 - Shimmy Weitzhandler
8
对于.NET而言,这是错误的;你只能得到36个字符!在C#可视化器中可以获得括号(38个字符),但在代码中则不行! - stevehipwell

44

在这里做正确的事情是将其存储为uniqueidentifier - 这样就可以完全索引化等等。如果不得已必须将其存储为字符串,则长度实际上取决于您选择如何对其进行编码。作为十六进制(也称为基础16编码)而没有连字符,它将是32个字符(每个字节两个十六进制数字),因此是char(32)

但是,您可能希望保留连字符。如果您的数据库不支持原生的blob / guid,但空间有限,则可以使用Base64编码并删除==填充后缀;这给您提供了22个字符,因此是char(22)。无需使用Unicode,也不需要可变长度-例如,nvarchar(max)是一个不好的选择。


2
为什么 uniqueidentifer 是完全可索引的,但 binary(16) 却不是? - BaltoStar

9
我相信GUIDs的长度受限于16个字节(或32个字节,如果是ASCII十六进制等效形式)。

6

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)

:-)


1
理论上是可以的。但是随着今天巨大的硬盘,使用类似varchar(50)之类的东西更加实际。因此,如果您存储类似于“1234ABC-ABCD-12AB-34CD-FEDCBA12”之类的内容,则不必来回翻译它。您建议的比仅读取/写入值稍微更加CPU密集,而这正是您在实践中想要的。 - LongChalk

6

如果你按照以下方式进行操作,那么这个值是22字节:

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

2

二进制字符串存储原始字节数据,而字符字符串则存储文本。在存储十六进制值(如SID、GUID等)时,请使用二进制数据。uniqueidentifier数据类型包含全局唯一标识符或GUID。此值通过使用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来为表填充默认值。在为CustomerID列分配NEWID()的默认值时,每个新的和现有的行都具有唯一的值。

-- 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。 没有主键的表会引发麻烦。假设你有一百万个客户,你想要一行数据 - WHERE CustomerID='xxx' - 你是想扫描整个表还是直接查找?这种双重搜索 - ID=524332和CustomerID='xxx'是非常强大的搜索。它既非常快,又非常安全(没有人能够通过暴力猜测GUID)。 - LongChalk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接