SQL Server中的char、nchar、varchar和nvarchar有什么区别?

713

nvarchar 是什么意思?

charncharvarcharnvarchar 在 SQL Server 中有什么区别?

12个回答

974

为了澄清或总结一下...

  • ncharnvarchar 能够存储 Unicode 字符。
  • charvarchar 不能够存储 Unicode 字符。
  • charnchar固定长度的,它们会为您指定的字符数 保留存储空间,即使您没有使用完所有该空间。
  • varcharnvarchar可变长度的,它们仅会为您存储的字符使用空间。它不会像charnchar那样保留存储空间

由于ncharnvarchar需要使用两倍的存储空间,所以只有在需要Unicode支持时才明智地使用它们。


20
char和varchar并不是用于存储Unicode的,但是通过一些额外的编码技巧和额外的逻辑,您仍然可以误用[var]char字段来存储Unicode。 - Wim ten Brink
11
根据整理方式不同,nvarcharvarchar版本是否会占用两倍的存储空间是不确定的 如我的答案所示 - Martin Smith
9
保留存储有什么优势? - mlissner
4
最后一点:在大多数情况下,使用Unicode的nchar和nvarchar仍然更好,具有更好的排序、用户灵活性和消除未来的兼容性问题。顺便说一句,对于这种情况,存储空间不是问题,因为使用非Unicode排序是很麻烦的,并且内存价格将来会继续下降。 - Jaison Varghese
8
@BenCaine char(20)将使用20个字节(假设使用8位排序); varchar(20)将使用len(data)+2个字节,即对于20个字节的数据为22个字节,但对于10个字节的数据只需12个字节。额外的两个字节是长度记录。如果您的数据始终是完整长度,请使用char,因为它可以节省空间并且可能更快。请不要使用varchar(1),或者比varchar(4)更小的任何内容。在varchar格式中,一个单独字符使用三个字节,因此char(3)永远不会使用比varchar(3)更多的空间。 - Richard Gadsden
显示剩余7条评论

111
到目前为止,所有的答案都表明varchar是单字节,nvarchar是双字节。事实上,这取决于排序规则,如下所示:(参考链接)
DECLARE @T TABLE
(
C1 VARCHAR(20) COLLATE Chinese_Traditional_Stroke_Order_100_CS_AS_KS_WS,
C2 NVARCHAR(20)COLLATE  Chinese_Traditional_Stroke_Order_100_CS_AS_KS_WS
)

INSERT INTO @T 
    VALUES (N'中华人民共和国',N'中华人民共和国'),
           (N'abc',N'abc');

SELECT C1,
       C2,
       LEN(C1)        AS [LEN(C1)],
       DATALENGTH(C1) AS [DATALENGTH(C1)],
       LEN(C2)        AS [LEN(C2)],
       DATALENGTH(C2) AS [DATALENGTH(C2)]
FROM   @T  

返回结果

enter image description here

请注意,VARCHAR 版本仍未表示“华”和“国”字符,并被静默地替换为“?”。

实际上,在该排序规则中仍然没有任何可以由单个字节表示的中文字符。唯一的单字节字符是典型的西方ASCII字符集。

因此,从 nvarchar(X) 列插入到 varchar(X)可能会因截断错误而失败(其中X在两个实例中都相同)。

SQL Server 2012 添加了支持 UTF-16 的SC(补充字符)排序规则。在这些排序规则中,单个 nvarchar 字符可能需要占用2或4个字节。


5
我正在寻找的答案类型。此外,为了节省像我这样的人的时间,非英文文本翻译为“中华人民共和国”。 - Igand

44

nchar和char的操作方式基本相同,nvarchar和varchar也是如此。它们之间唯一的区别在于nchar/nvarchar存储Unicode字符(如果需要使用扩展字符集,则必不可少),而varchar则不存储。

由于Unicode字符需要更多的存储空间,因此nchar/nvarchar字段需要两倍的空间(例如,在早期版本的SQL Server中,nvarchar字段的最大大小为4000)。

这个问题是这个的副本。


6
你忘了一件事情:nchar是使用固定长度的,所以nchar(10)始终需要接收十个字符。而varchar(10)确实是Unicode,可以接受任意数量的字符,最多不超过10个字符。还可以参考 http://msdn.microsoft.com/en-us/library/ms186939.aspx 。 - Wim ten Brink

40

补充一些内容: nchar - 将空格添加到数据的末尾。 nvarchar - 不会在数据末尾添加空格。

因此,如果您要按'nchar'字段筛选数据集,则可能需要使用RTRIM删除空格。 例如, nchar(10)字段名为BRAND,存储单词NIKE。 它将6个空格添加到该单词的右侧。 因此,在筛选时,表达式应为: RTRIM(Fields!BRAND.Value)=“NIKE”

希望这可以帮助某些人,因为我刚刚也遇到了一些问题!


每个选项都在我的 SQL Server 中添加尾随空格... :/ - Gustavo Contreiras

28

根据现有答案,我试图总结并纠正如下:

首先,charnchar 会始终使用一定的存储空间,即使要存储的字符串比可用空间小,而 varcharnvarchar 只会使用足够存储该字符串的存储空间(加上两个字节的开销,可能是用来存储字符串长度)。因此记住,“var”表示“variable”,即可变空间。

第二个重要点是,ncharnvarchar 使用每个字符恰好两个字节来存储字符串,而 charvarchar 使用由排序代码页确定的编码来存储字符串,通常每个字符恰好使用一个字节(虽然有例外情况,请参见下文)。通过使用每个字符两个字节,可以存储非常广泛的字符范围,因此基本要记住的是,当您需要国际化支持时,ncharnvarchar 往往是更好的选择,这也是您想要的。

现在是一些更详细的信息。

首先,ncharnvarchar 列始终使用 UCS-2 存储数据。这意味着每个字符将使用恰好两个字节,并且 ncharnvarchar 字段可以存储基本多文种平面(BMP)中的任何 Unicode 字符。但并非所有 Unicode 字符都可以存储。例如,根据维基百科,埃及象形文字的代码点超出了 BMP 的范围。因此,可以在 UTF-8 和其他真正的 Unicode 编码中表示的 Unicode 字符串可能无法存储在 SQL Server 的 ncharnvarchar 字段中,而写成埃及象形文字的字符串将是其中之一。幸运的是,您的用户可能不会以该脚本编写,但这也是需要记住的事情!

其他帖子中提到的令人困惑但有趣的一点是,charvarchar字段可能对于某些字符每个字符使用两个字节,如果排序规则代码页需要的话。(Martin Smith在他展示如何使用Chinese_Traditional_Stroke_Order_100_CS_AS_KS_WS的示例中给出了一个很好的例子。请查看它。)

更新:截至SQL Server 2012年,终于有了UTF-16编码页,例如Latin1_General_100_CI_AS_SC,可以真正覆盖整个Unicode范围。


16

nchar[(n)] (国家字符)

  • 固定长度的Unicode字符串数据。
  • n定义字符串长度,必须是1到4,000之间的值。
  • 存储大小为n个字节的两倍。

nvarchar [(n | max)] (国家字符变长)

  • 可变长度的Unicode 字符串数据。
  • n定义字符串长度,可以是1到4,000之间的值。
  • max表示最大存储大小为2^31-1字节(2 GB)。
  • 存储大小(以字节为单位)等于实际输入数据的长度加上2个字节。

char [(n)] (字符)

  • 固定长度的、非Unicode字符串数据。
  • n定义字符串长度,必须是1到8,000之间的值。
  • 存储大小为n个字节。

varchar [(n | max)] (字符变长)

  • 可变长度的、非Unicode字符串数据。
  • n定义字符串长度,可以是1到8,000之间的值。
  • max表示最大存储大小为2^31-1字节(2 GB)。
  • 存储大小等于输入数据的实际长度加上2个字节。

15
  • char:最大长度为8000个字符的定长字符数据。
  • nchar:最大长度为4000个字符的定长Unicode数据。
  • Char = 8位长度
  • NChar = 16位长度

char 无法具有8位长度。它不必存储长度,并且固定长度可高达8000个字符。 - John B. Lambe

12

nchar(10) 是一个长度为 10 的固定长度 Unicode 字符串。nvarchar(10) 是一个可变长度的 Unicode 字符串,最大长度为 10。通常,如果所有数据值都是 10 个字符,应该使用前者;如果长度不同,则应使用后者。


错误的比较 - 问题涉及到 nchar 和 varchar,而不是 nchar 和 nvarchar。 - Luke Bennett

10

nchar需要比nvarchar更多的空间。

例如,

nchar(100)将始终存储100个字符,即使您只输入了5个字符,其余的95个字符也会用空格填充。 在nvarchar(100)中存储5个字符将节省5个字符的空间。


7
这段话的大意是:这并不完全正确,因为你需要使用 char(100) 填充最多100个字符。当你在数据库中存储电话号码或固定长度的订单号时,可以使用此选项。由于字段长度是固定的,你别无选择,只能填满最大数量的字符。但是,如果每条记录的数据都是100个字符,那么 char(100) 的存储空间比 varchar(100) 小,因为它不需要长度指示:每个值都恰好是100个字符。 - Wim ten Brink

8

它们的区别如下:

  1. n[var]char 存储 Unicode 编码,而 [var]char 只存储单字节字符。
  2. [n]char 需要精确指定固定长度的字符,而 [n]varchar 可以接受不同长度的变量。

另一个区别是长度。nchar 和 nvarchar 的长度最大可以是 4,000 个字符,而 char 和 varchar 最多可达 8000 个字符。但对于 SQL Server,您还可以使用 [n]varchar(max),它可以处理高达 2,147,483,648 个字符(两个千兆字节,即有符号 4 字节整数)。


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