nvarchar 是不是总是将每个字符存储在两个字节中?

Posted

技术标签:

【中文标题】nvarchar 是不是总是将每个字符存储在两个字节中?【英文标题】:Does an nvarchar always store each character in two bytes?nvarchar 是否总是将每个字符存储在两个字节中? 【发布时间】:2011-06-10 11:03:29 【问题描述】:

我曾经(也许是天真地)假设在 SQL Server 中,nvarchar 会将每个字符存储在两个字节中。但情况似乎并非总是如此。那里的文档表明某些字符可能需要更多字节。有人有明确的答案吗?

【问题讨论】:

【参考方案1】:

是的,它使用 2 个字节,使用 datalength 来获取存储大小,您不能使用 LEN,因为 LEN 只计算字符,请参见此处:The differences between LEN and DATALENGTH in SQL Server

DECLARE @n NVARCHAR(10)
DECLARE @v VARCHAR(10)

SELECT @n = 'A', @v='A'

SELECT  DATALENGTH(@n),DATALENGTH(@v)

---------
2 1

这是在线图书的内容:http://msdn.microsoft.com/en-us/library/ms186939.aspx

字符数据类型 固定长度、nchar 或 可变长度、nvarchar、Unicode 数据并使用 UNICODE UCS-2 字符集。

nchar [ ( n ) ]

固定长度的 Unicode n 个字符的字符数据。 n 必须 是从 1 到 4,000 的值。这 存储大小是 n 字节的两倍。这 nchar 的 ISO 同义词是国家的 字符和国家字符。

nvarchar [ ( n | max ) ]

可变长度 Unicode 字符 数据。 n 可以是从 1 到 4,000。 max 表示最大值 存储大小为 2^31-1 字节。这 存储大小(以字节为单位)是两倍 输入的字符数 + 2 字节。输入的数据可以为0 个字符的长度。 ISO 同义词 对于 nvarchar 是国家字符变化 和民族性格不同。

也就是说 unicode 压缩是在 SQL Server 2008 R2 中引入的,因此它可能会将 ascii 存储为 1 个字节,您可以在此处阅读有关 unicode 压缩的信息

SQL Server 2008 R2 : A quick experiment in Unicode Compression SQL Server 2008 R2 : Digging deeper into Unicode compression More testing of Unicode Compression in SQL Server 2008 R2

【讨论】:

当然,但这是一个沼泽标准字母。在 SQL Server 的 UCS-2 实现中,它是否有时将其存储在 4 个字符中以用于不太常见的字符?例如,在这篇文章msdn.microsoft.com/en-us/library/bb330962(v=sql.90).aspx 中它说“因为 UCS-2 只允许对 65,536 个不同的代码点进行编码,所以它本身并不处理补充字符,而是将补充字符视为一对未定义的 Unicode 代理字符,当配对在一起,定义一个补充字符。” 不,我从未见过它使用超过 2 个字符...也许那些不太常见的字符无法存储..您有一个示例...将其粘贴到代码中看看你会得到什么 我最初的困惑出现了,因为我看到有人在博客上说他们在一张桌子上使用了 sp_spaceused,由于某种原因,当他们使用 nvarchar 时,与 varchar 相比,它占用了两倍以上的空间。也许这可能是由于更多的页面,或者其他此类非数据 gumf 占用了额外的大小? sp_spaceused 还显示可用空间和非聚集索引空间。如果表是碎片化的,它将占用更多空间 >可以存储 2 字节字符(尽管它们在内部保存为 UCS-2) - 请参阅我的答案中的 GB18030 链接【参考方案2】:

鉴于有超过 65536 个字符,很明显一个字符不可能只容纳两个八位字节(即 16 位)。

SQL Server 与大多数 Microsoft 产品(Windows、.NET、NTFS 等)一样使用 UTF-16 存储文本,其中一个字符占用两个或四个八位字节,尽管正如 @SQLMenace 指出的那样,当前版本的 SQL Server 使用压缩来减少这种情况。

【讨论】:

有趣——从我在网上看到的其他东西中,他们提到 SQL Server 使用 UCS-2 来存储文本。 那么你是说一个 nvarchar 字符可能需要 4 个字节?【参考方案3】:

我对这个问题的理解是,SQL server 内部使用的是 UCS-2,但是它的 UCS-2 实现已经被破解以支持a subset of characters of up to 4 bytes in the GB18030 character set,它被存储为 UCS-2 但被数据库引擎透明地转换回来查询时转换为多字节字符。

不完全支持代理/补充字符 - 许多 SQL 服务器字符串函数的实现不支持代理对,详细信息 here。

【讨论】:

以上是关于nvarchar 是不是总是将每个字符存储在两个字节中?的主要内容,如果未能解决你的问题,请参考以下文章

为长文本字符串覆盖流利的 NHibernate nvarchar(MAX) 而不是 nvarchar(255)

将列从 varchar 转换为 nvarchar 是不是会更改存储在列中的字符串的编码?

减小我的 NVARCHAR 列的大小是不是有好处

mysql

SQL中varchar和nvarchar有啥区别?

varchar2 和nvarchar2的选择