题 varchar和nvarchar有什么区别?


就是这样 nvarchar 支持多字节字符?如果是这种情况,除了存储问题之外,除了使用之外,是否真的有任何意义 varchars


1169
2017-09-27 19:34


起源


我喜欢incomudro的观点,这就是让我在第一时间挖掘varchar和nvarchar之间差异的原因。我们针对SQL Server数据库的Java应用程序使用myBatis,默认情况下它似乎将字符串作为nvarchar发送(仍不确定如何(或如果)可重写)。一个简单的查询显示为一个巨大的性能问题,因为我将它选择的列定义为varchar,而不是nvarchar,它忽略了列上的索引。 - Sean Read
这个链接可以帮到你 codefari.com/2015/10/... - Singh


答案:


一个 nvarchar 列可以存储任何Unicode数据。一个 varchar 列仅限于8位代码页。有些人认为 varchar 应该使用,因为它占用更少的空间。我相信这不是正确的答案。代码页不兼容性很痛苦,Unicode可以解决代码页问题。现在有了廉价的磁盘和内存,实际上没有理由浪费时间来处理代码页了。

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

如果您与仅使用ASCII的应用程序连接,我仍然建议在数据库中使用Unicode。操作系统和数据库整理算法将更好地与Unicode一起使用。 Unicode避免了与接口连接时的转换问题 其他 系统。你将为未来做准备。您可以随时验证您的数据是否仅限于7位ASCII,无论您需要维护哪些遗留系统,即使在享受完整Unicode存储的一些优势的同时也是如此。


1437
2017-09-29 02:16



这是一个很好的信息。所以,如果我推断选择最终成为 - 哪种资源更便宜:处理器+开发开销还是存储? - Matt Cashatt
@MatthewPatrickCashatt - 你可以这样看。但如果你想象一个光荣的世界 所有 文本数据是用Unicode编写的,开发人员根本不需要考虑编码内容是什么,并且根本不会发生一整类错误,那么你就会发现根本就没有选择。 - Jeffrey L Whitledge
varchar不限于所有排序规则中的8位代码页 - Martin Smith
@Martin Smith - 在这些情况下,varchar带来的微小优势(紧凑型存储)消失了。我猜varchar甚至比我想象的更糟糕! - Jeffrey L Whitledge
@PeterAllenWebb - 您可以“存储”任何Unicode数据,因为UTF-16中的代理项对可以存储在UCS-2中,就好像它们是字符一样。这将透明地用于数据存储和检索。现在,你不能做的是在BMP之外获得可靠的案例转换和比较,但我没有对此做出任何声明。因此,如果您有许多要进行处理的Desseret文本,最好在数据库之外执行此操作。但是把它存放在那里就好了。 (当然,varchar也不会帮助你!) - Jeffrey L Whitledge


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

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

有了这些知识,请使用与输入数据匹配的任何一种(ASCII v.Unicode)。


225
2017-09-27 19:37



是否存在像varchar这样的限制无法存储Unicode数据?它的全部是1和0。我可以将中文内容保存为varchar就好了。我只是指定它的UTF-8。那怎么工作呢? - Nishant
@Nishant迟到了 回答:当然你可以在UTchar中存储UTF-8,但它会破坏SQL Server字符串函数。如果您在应用程序中执行所有搜索/转换,那么您可以这样做(但有什么好处?)。只有SS支持的Unicode编码是UCS-2(是的,在SS2k16之前不是UTF-16),并且其字符串函数仅适用于该编码。 BTW指数怎么样?如果你想存储任意数据,你最好使用二进制。 - Adriano Repetti
是的,它只是打破了字符串搜索功能。 - Nishant
所以,你知道......它不起作用。那就像存储一个 float 变成一个 int 然后,“确保小数点丢失。”只是不要。 - user7116


我总是使用nvarchar,因为它允许我正在构建的任何数据,以承受我投入的任何数据。我的CMS系统偶然会中文,因为我使用的是nvarchar。如今,任何新应用程序都不应该真正关注所需的空间量。


61
2017-09-27 19:37



新应用程序不应该关注空间限制的想法有些短视,任何处理中大型企业级数据库的人都会很乐意告诉你,完全不正确。 - Frater
为了冒昧地在tags2k的口中说出话题,我认为更准确的说法可能是“任何新的应用程序都应该更加关注所需的空间而不是关于国际化和其他字符集问题”。 - Cowan
谢谢Cowan,这就是我2年前的意思。圣烟! - tags2k
“现在,任何新的应用程序都不应该真正关注所需的空间量。” - 除非您使用免费的云存储,否则付费计划是$的值得考虑的跳转(请参阅AppHarbor SQL Server共享计划)。 - ganders
@ganders哈尔!你就在那里。广义陈述充其量只是暂时正确的。计算绝对是一个波动和迂回的游戏。我非常担心我在Windows Azure CCP上使用了多少空间。这就是说我“永远不会”使用varchar而不是nvarchar。哦,我只是反驳自己? - rism


在这里你可以看到它们之间的差异 varchar 和 nvarchar

Enter image description here

Enter image description here

Enter image description here

Enter image description here

参考: SqlHints.com

有关Nvarchar和varchar的更多信息,请参阅 这篇博文


42
2017-11-24 08:45



请发布实际文字而不是截图。其他人无法复制和粘贴或搜索您的图像。 看这里 详情。谢谢。 - Pang
他们甚至不能在某些防火墙内看到图像! - Allan Bowe


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

如果你的NLS_CHARACTERSET是像UTF8这样的Unicode编码,那很好。使用VARCHAR和NVARCHAR几乎完全相同。现在停止阅读,就去吧。否则,或者如果您无法控制Oracle字符集,请继续阅读。

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

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

存储空间怎么样? VARCHAR通常是高效的,因为字符集/编码是为特定区域设置定制的。 NVARCHAR字段以UTF-8或UTF-16编码存储,基于NLS设置具有讽刺意味。 UTF-8对于“西方”语言非常有效,同时仍然支持亚洲语言。 UTF-16对亚洲语言非常有效,同时仍然支持“西方”语言。如果担心存储空间,请选择NLS设置以使Oracle根据需要使用UTF-8或UTF-16。

处理速度怎么样?大多数新的编码平台本身都使用Unicode(Java,.NET,甚至多年前的C ++ std :: wstring!),所以如果数据库字段是VARCHAR,它会强制Oracle在每次读取或写入时在字符集之间进行转换,这样做不太好。使用NVARCHAR可以避免转换。

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


29
2017-10-07 18:08



这是一个非常好的答案,除了问题是关于sql-server。 - stimms


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


15
2017-09-27 19:36





我的两分钱

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

  2. 数据类型可能因不同的DBMS(数据库管理系统)而异:
    知道每个数据库的数据类型略有不同,VARCHAR并不代表所有数据类型。虽然SQL Server具有VARCHAR和NVARCHAR,但Apache / Derby数据库仅具有VARCHAR,而VARCHAR具有Unicode。


13
2018-04-19 09:53



但是当然如果你正确编写代码(即使用参数化查询等),那么第1点的风险就更小了。 - Paul


主要 为nvarchar 存储Unicode字符和 VARCHAR 存储非Unicode字符。

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

这意味着unicodes每个字符使用2个字节进行存储,非单元只使用每个字符一个字节进行存储。这意味着与非unicode相比,unicodes需要双倍的存储容量。


11
2017-12-14 12:09





你是对的。 nvarchar 存储Unicode数据 varchar 存储单字节字符数据。除存储差异外(nvarchar需要两倍的存储空间 varchar),你已经提到过,更喜欢的主要原因 nvarchar 过度 varchar 将是国际化(即以其他语言存储字符串)。


9
2017-09-27 19:42





我会说,这取决于。

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

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


8
2018-01-25 10:19