varchar和nvarchar有什么区别?


1353

仅仅是nvarchar支持多字节字符吗?如果是这样的话,除了存储方面的问题,真的有什么要使用的varchars吗?


6
我喜欢incomudro的观点,这就是促使我首先研究varchar和nvarchar之间的区别的原因。我们针对SQL Server数据库的Java应用程序使用myBatis,默认情况下,myBatis似乎将字符串作为nvarchar发送(仍然不确定如何(或是否)可重写)。一个简单的查询显示为一个巨大的性能问题,因为我将针对它选择的列定义为varchar,而不是nvarchar,并且它忽略了该列的索引。
肖恩(Sean)

Answers:


1651

nvarchar列可以存储任何Unicode数据。甲varchar柱被限制为一个8位的代码页。有人认为varchar应该使用它,因为它占用更少的空间。我相信这不是正确的答案。代码页不兼容是一种痛苦,而Unicode是解决代码页问题的方法。如今,借助廉价的磁盘和内存,确实没有理由再浪费时间浪费代码页了。

所有现代操作系统和开发平台内​​部都使用Unicode。通过使用nvarchar而不是varchar,您可以避免在每次从数据库读取或写入数据库时​​进行编码转换。转换需要时间,并且容易出错。从转换错误中恢复并不是一个简单的问题。

如果要与仅使用ASCII的应用程序接口,我仍然建议在数据库中使用Unicode。操作系统和数据库排序算法将与Unicode一起更好地工作。与其他系统连接时,Unicode避免了转换问题。您将为未来做准备。而且,即使享受完整的Unicode存储的某些优势,您也始终可以验证对于必须维护的任何旧版系统,数据都限制为7位ASCII。


8
这是很棒的信息。因此,如果我推断出选择最终成为其中一种资源(哪一种资源更便宜:处理器+开发开销或存储),我是否能正确理解这一点?
马特·卡察特

141
@MatthewPatrickCashatt-您可以那样看。但是,如果您想象一个光荣的世界,其中所有文本数据都采用Unicode,并且开发人员根本不必考虑其中的编码方式,并且根本不会发生一整类错误,那么您可以看到存在真的没有选择。
Jeffrey L Whitledge,2012年


8
@Martin Smith-在那种情况下,varchar赋予(紧凑存储)的微小优势就消失了。我猜varchar比我想象的还要糟糕!
Jeffrey L Whitledge,2012年

9
@PeterAllenWebb-您可以“存储”任何Unicode数据,因为UTF-16中的代理对可以像字符一样存储在UCS-2中。这将透明地用于数据存储和检索。现在,您不能做的是在BMP之外获得可靠的案例转换和比较,但是我对此没有任何主张。因此,如果您要处理许多Desseret文本,则最好在数据库外部进行处理。但是将其存储在此处就很好了。(当然,varchar也不会在那里帮助您!)
Jeffrey L Whitledge 2013年

259

varchar:可变长度的非Unicode字符数据。数据库排序规则确定数据使用哪个代码页存储。

nvarchar:可变长度的Unicode字符数据。取决于数据库排序规则进行比较。

掌握了这些知识之后,请使用与您的输入数据相匹配的任何一种(ASCII与Uni​​code)。


5
是否有诸如varchar不能存储Unicode数据的限制?其全为1和0。我可以将中文内容另存为varchar,这对我的DB来说很好。我只是指定了它的UTF-8。那如何运作呢?
Nishant 2014年

3
@Nishant最新答案:当然,您可以将UTF-8存储在varchar中,但这会破坏SQL Server字符串函数。如果您在应用程序中执行所有搜索/转换,那么可以,您可以这样做(但是这样做有什么好处?)。只有SS支持的Unicode编码是UCS-2(是,不是SS2k16之前的UTF-16),并且其字符串函数仅适用于该编码。顺便说一句,指数呢?如果要存储任意数据,则最好改用二进制。
Adriano Repetti 2015年

是的,它只是破坏了字符串搜索功能。
Nishant 2015年

8
因此,您知道...它“不起作用”。这就好比将a float存入an int并继续进行,“请确保小数点丢失。” 只是不要。
user7116

70

我一直使用nvarchar,因为它允许我构建的所有内容都可以承受我向它抛出的几乎所有数据。我的CMS系统偶然使用了中文,因为我使用了nvarchar。如今,任何新应用程序都不必真正关心所需的空间量。


25
新应用程序不应该关注空间限制的想法有些短视,任何在大中型企业级别上处理过数据库的人都会很高兴地告诉您,这是完全错误的。
Frater,2010年

60
为了自由地将单词放在tag2k的嘴里,我认为更准确的说法可能是“与新版本相比,任何新应用都应该更加关注所需的空间,而不是国际化和其他字符集问题。”
科恩2010年

1
“如今,任何新的应用程序都不应该真正关心所需的空间量。” -除非您使用免费的云存储,否则付费计划是$的相当大的增长(请参阅AppHarbor SQL Server共享计划)。
甘德斯2014年

3
@ganders l!你就在那里 广义语句充其量只是暂时的正确。计算绝对是一个摇摆和回旋的游戏。我绝对关心我在Windows Azure CCP上使用了多少空间。那就是说我将“永远”不使用varchar而不是nvarchar。噢,我只是矛盾了吗?
rism

1
@rism,我相信您"never"至少在技术上消除了与使用引号相矛盾的风险。
Smandoli 2014年

30

这取决于如何安装Oracle。在安装过程中,将设置NLS_CHARACTERSET选项。您可以通过查询找到它SELECT value$ FROM sys.props$ WHERE name = 'NLS_CHARACTERSET'

如果您的NLS_CHARACTERSET是Unicode编码(例如UTF8),那就太好了。使用VARCHAR和NVARCHAR几乎相同。现在停止阅读,继续阅读。否则,或者如果您无法控制Oracle字符集,请继续阅读。

VARCHAR —数据以NLS_CHARACTERSET编码存储。如果同一服务器上还有其他数据库实例,则您可能会受到这些实例的限制。反之亦然,因为您必须共享设置。这样的字段可以存储可以使用该字符集进行编码的任何数据,而别无其他。因此,例如,如果字符集为MS-1252,则只能存储英文字母,少数带重音符号的字母以及其他几个字母(如€和-)。您的应用程序仅对少数地区有用,无法在世界上其他任何地方运行。因此,它被认为是一个坏主意。

NVARCHAR —数据以Unicode编码存储。支持每种语言。一个好主意。

那存储空间呢?VARCHAR通常是有效的,因为字符集/编码是针对特定语言环境自定义设计的。NVARCHAR字段以具有讽刺意味的NLS设置为基础,以UTF-8或UTF-16编码存储。UTF-8对于“西方”语言非常有效,同时仍支持亚洲语言。UTF-16对于亚洲语言非常有效,同时仍支持“西方”语言。如果担心存储空间,请选择一个NLS设置以使Oracle适当地使用UTF-8或UTF-16。

处理速度如何?大多数新的编码平台都本机使用Unicode(Java,.NET,甚至几年前的C ++ std :: wstring!),因此,如果数据库字段为VARCHAR,它将迫使Oracle在每次读取或写入时在字符集之间进行转换,效果不是很好。使用NVARCHAR避免了转换。

底线:使用NVARCHAR!它避免了限制和依赖性,适合存储空间,并且通常也最适合性能。


42
这是一个很好的答案,只是问题与sql-server有关。
stimms

21

nvarchar将数据存储为Unicode,因此,如果要在数据列中存储多语言数据(一种以上的语言),则需要N变体。


16

我的两分钱

  1. 如果未使用正确的数据类型,则索引可能会失败:
    在SQL Server中:当您在VARCHAR列上有一个索引并将其显示为Unicode字符串时,SQL Server不会使用该索引。当您将BigInt呈现给包含SmallInt的索引列时,也会发生同样的事情。即使BigInt小到足以成为SmallInt,SQL Server也无法使用索引。另一种解决方法是不存在此问题(将SmallInt或Ansi-Code提供给已索引的BigInt或NVARCHAR列时)。

  2. 数据类型在不同的DBMS(数据库管理系统)之间可能会有所不同:
    知道每个数据库都有略有不同的数据类型,而VARCHAR并非在每个地方都具有相同的含义。虽然SQL Server具有VARCHAR和NVARCHAR,但是Apache / Derby数据库只有VARCHAR,而VARCHAR是Unicode的。


但是可以肯定的是,如果您正在正确地编写代码(即使用参数化查询等),则点1的风险较小。
保罗,

14

主要是nvarchar存储Unicode字符,而varchar存储非Unicode字符。

“ Unicode”表示16位字符编码方案,它允许将来自许多其他语言(如阿拉伯语,希伯来语,中文,日语)的字符编码为单个字符集。

这意味着unicode每个字符使用2个字节来存储,而nonunicodes每个字符仅使用一个字节来存储。这意味着与非unicode相比,unicode需要两倍的存储容量。


10

你是对的。nvarchar存储Unicode数据,同时varchar存储单字节字符数据。除了存储差异(nvarchar需要两倍的存储空间varchar),您已经提到的,主要原因宁愿nvarcharvarchar将国际化(在其他语言中即存储字符串)。


10

我会说,这取决于。

如果您开发一个桌面应用程序,并且该操作系统使用Unicode(像当前所有的Windows系统一样)并且语言本身就支持Unicode(默认字符串是Unicode,例如Java或C#),那么请使用nvarchar。

如果您开发一个Web应用程序,其中字符串以UTF-8形式出现,而语言是PHP(仍然不支持Unicode本机(在5.x版本中)),那么varchar可能是一个更好的选择。


9

尽管NVARCHAR存储Unicode,但您应在排序规则的帮助下考虑,也可以使用VARCHAR和保存本地语言的数据。

试想一下以下情况。

您数据库的排序规则是波斯语,您在VARCHAR(10)数据类型中保存了一个类似“علی”(阿里的波斯语写作)的值。没问题,DBMS仅使用三个字节来存储它。

但是,如果要将数据传输到另一个数据库并查看正确的结果,则目标数据库必须与目标(在本示例中为Persian)具有相同的排序规则。

如果目标排序规则不同,则会在目标数据库中看到一些问号(?)。

最后,请记住,如果您正在使用庞大的数据库来使用本地语言,我建议您使用位置而不是使用太多空间。

我相信设计可以有所不同。这取决于您工作的环境。


8

我看了一下答案,很多人似乎建议使用nvarcharover varchar,因为空间不再是问题,因此启用Unicode进行少量存储不会造成任何危害。好吧,当您想在列上应用索引时,情况并非总是如此。SQL Server可以索引的字段的大小限制为900字节。因此,如果您有一个,varchar(900)您仍然可以为其编制索引,但不能varchar(901)。使用nvarchar,字符数减半,因此您最多可以索引nvarchar(450)。因此,如果您有信心不需要nvarchar,我不建议您使用它。

通常,在数据库中,我建议坚持使用所需的大小,因为您可以随时进行扩展。例如,一个在工作中的同事曾经认为,使用nvarchar(max)色谱柱不会造成任何危害,因为我们完全没有存储问题。稍后,当我们尝试在该列上应用索引时,SQL Server拒绝了此操作。但是,如果他从even开始varchar(5),那么我们可以稍后将其扩展到所需的范围,而不会出现问题,这将需要我们制定现场迁移计划来解决此问题。


7

nVarchar将帮助您存储Unicode字符。如果要存储本地化的数据,这是一种方法。


7

如果使用单个字节存储字符,则有256种可能的组合,因此您可以保存256个不同的字符。排序规则是一种模式,它定义了字符以及对其进行比较和排序的规则。

最常见的是Latin1(ANSI)1252。单字节字符集也不足以存储许多语言使用的所有字符。例如,某些亚洲语言有数千个字符,因此每个字符必须使用两个字节。

Unicode标准

当在网络中使用使用多个代码页的系统时,变得难以管理通信。为了使事情标准化,ISO和Unicode联盟引入了Unicode。Unicode使用两个字节存储每个字符。即可以定义65,536个不同的字符,因此几乎所有字符都可以用Unicode覆盖。如果两台计算机使用Unicode,则每个符号都将以相同的方式表示,并且不需要转换-这是Unicode背后的思想。

SQL Server具有两类字符数据类型:

  • 非Unicode(char,varchar和text)
  • Unicode(nchar,nvarchar和ntext)

如果我们需要保存来自多个国家的字符数据,请始终使用Unicode。


6

我必须在这里说(我意识到我可能要对自己敞开心to!),但是可以肯定的是,唯一一次NVARCHAR实际上比所有排序规则都更有用(注意那里的更多!)VARCHAR。依赖系统和数据库本身内部是相同的...?如果不是这样,则无论如何都必须进行归类转换,因此它VARCHAR与一样可行NVARCHAR

除此之外,某些数据库系统(例如SQL Server(2012年之前))的页面大小大约为1。8K。因此,如果您要存储未存储在诸如a TEXTNTEXTfield之类的内容中的可搜索数据,则VARCHAR可以提供全部8k的空间,而NVARCHAR仅提供4k(双字节,双倍空间)。

概括地说,我想其中之一的使用取决于:

  • 项目或背景
  • 基础设施
  • 数据库系统


6

Varchar(n)和之间的主要区别nvarchar(n)是: 在此处输入图片说明

Varchar(可变长度,非Unicode字符数据)大小最大为8000。1.这是可变长度数据类型

  1. 用于存储非Unicode字符

  2. 每个字符占用1个字节的空间

在此处输入图片说明

Nvarchar:可变长度Unicode字符数据。

1.这是一个可变长度的数据类型

2.用于存储Unicode字符。

  1. 数据以Unicode编码存储。支持每种语言。(例如阿拉伯语,德语,印地语等语言)

6

Jeffrey L Whitledge的信誉得分约为47000,建议使用nvarchar

信誉得分约为33200的所罗门·鲁兹基建议:不要总是使用NVARCHAR。这是非常危险的,而且往往是昂贵的态度/方法。

varchar和nvarchar SQL Server数据类型之间的主要性能差异是什么?

https://www.sqlservercentral.com/articles/disk-is-cheap-orly-4

双方都享有如此高的声誉,学习型sql服务器数据库开发人员会选择什么?

如果您选择不一致,则会在答案和评论中有许多关于性能问题的警告。

有关于性能的pro / con nvarchar注释。

有关于性能的pro / con varchar注释。

我对具有数百列的表有特殊的要求,这本身可能是不寻常的?

我选择varchar以避免接近SQL * server 2012的8060字节表记录大小限制。

对我来说,使用nvarchar超过了8060字节的限制。

我还认为我应该将相关代码表的数据类型与主要中央表的数据类型进行匹配。

我已经看到南澳大利亚州政府在以前的经验丰富的数据库开发人员的工作场所使用varchar列,在该行中,表行数将达到数百万甚至更多(在非常大的情况下,很少有nvarchar列,如果有的话)表),因此预期的数据行量可能会成为此决策的一部分。


1

nvarchar相比varchar为了使我们的代码没有错误(类型不匹配)而使用,是安全的,因为还nvarchar允许使用Unicode字符。当我们where在SQL Server查询中使用条件并且使用=运算符时,它有时会引发错误。可能的原因是我们的映射列将在中定义varchar。如果我们在nvarchar此问题中定义它,则不会发生。我们仍然坚持varchar并避免出现此问题,我们最好使用LIKE关键字而不是=

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.