ChatGPT解决这个技术问题 Extra ChatGPT

varchar 和 nvarchar 有什么区别?

只是 nvarchar 支持多字节字符吗?如果是这样的话,除了存储问题之外,使用 varchars 真的有什么意义吗?

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

l
lazyCrab

nvarchar 列可以存储任何 Unicode 数据。 varchar 列仅限于 8 位代码页。有些人认为应该使用varchar,因为它占用的空间较小。我相信这不是正确的答案。代码页不兼容是一件痛苦的事,而 Unicode 是解决代码页问题的方法。现在有了便宜的磁盘和内存,真的没有理由再浪费时间在代码页上乱搞了。

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

如果您正在与仅使用 ASCII 的应用程序交互,我仍然建议在数据库中使用 Unicode。操作系统和数据库排序算法将更好地与 Unicode 配合使用。 Unicode 在与其他系统交互时避免了转换问题。你将为未来做准备。对于您必须维护的任何遗留系统,您始终可以验证您的数据是否仅限于 7 位 ASCII,即使在享受完整 Unicode 存储的一些好处的同时。


这是很好的信息。那么,如果我推断出选择最终会成为其中一种资源更便宜:处理器+开发开销还是存储,那么我是否正确理解了这一点?
@MatthewPatrickCashatt - 你可以这样看。但是如果你想象一个辉煌的世界,所有的文本数据都是 Unicode,开发人员根本不需要考虑某种编码是什么,而且根本不会发生一整类错误,那么你可以看到有真的别无选择。
@Martin Smith - 在这些情况下, varchar 赋予(紧凑存储)的微小优势消失了。我猜 varchar 比我想象的还要糟糕!
@PeterAllenWebb - 您可以“存储”任何 Unicode 数据,因为 UTF-16 中的代理对可以像字符一样存储在 UCS-2 中。这将透明地用于数据存储和检索。现在,你不能做的是在 BMP 之外获得可靠的案例转换和比较,但我没有对此发表任何声明。因此,如果您想要处理大量 Dessert 文本,最好在数据库之外进行处理。但是把它存放在那里就很好了。 (当然,varchar 也不会帮助你!)
u
user7116

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

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

有了这些知识,就可以使用与您的输入数据匹配的任何一个(ASCII 与 Unicode)。


有没有像 varchar 不能存储 Unicode 数据这样的限制?都是 1 和 0 。我可以将中文内容作为 varchar 保存到我的数据库中。我只是指定了它的 UTF-8。那是如何工作的呢?
@Nishant 迟到的答案:当然,您可以将 UTF-8 存储在 varchar 中,但它会破坏 SQL Server 字符串函数。如果您在应用程序中执行所有搜索/转换,那么可以,您可以这样做(但有什么好处?)。只有 SS 支持的 Unicode 编码是 UCS-2(是的,不是 SS2k16 之前的 UTF-16),其字符串函数仅适用于该编码。顺便说一句,指数呢?如果要存储任意数据,最好使用二进制文件。
是的,它只是破坏了字符串搜索功能。
所以,你知道......它不“工作”。这就像将 float 存储到 int 中,然后“肯定会丢失小数点”。只是不要。
可能在您事先知道类别内容的电子商务平台中,您可以将 varchar 用于仅英文或“标准”西方名称,而在其他地方您有名称、位置、产品描述内容 nvarchar 将是更好的选择
P
Peter Mortensen

我总是使用 nvarchar,因为它允许我正在构建的任何东西承受我扔给它的几乎任何数据。我的 CMS 系统不小心做了中文,因为我使用了 nvarchar。如今,任何新应用程序都不应该真正关心所需的空间量。


新应用不应该关心空间限制的想法有点短视,任何在大中型企业级别处理过数据库的人都会很乐意告诉你,完全不正确。
冒昧地说,我认为更准确的说法可能是“任何新应用程序都不太可能更关注所需的空间,而不是关注国际化和其他字符集问题”。
“如今,任何新应用程序都不应该真正关心所需的空间量。” - 除非您使用免费的云存储,否则付费计划是 $ 的一个相当大的跳跃(请参阅 AppHarbor SQL Server 共享计划)。
@ganders 嚎叫!你就在那儿。概括的陈述充其量只是暂时正确的。计算绝对是一个摇摆不定的迂回游戏。我绝对关心我在 Windows Azure CCP 上使用了多少空间。那就是说我“永远”不会在 nvarchar 上使用 varchar。哦,我只是自相矛盾吗?
@rism,我相信您消除了与您在 "never" 上使用引号的任何矛盾风险,至少在技术上是这样。
J
Jeremy Frank

这取决于 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!它避免了限制和依赖,适合存储空间,通常也最适合性能。


这是一个非常好的答案,除了问题是关于 sql-server 的。
最佳答案。我正在使用 varchar2,因为我的 db 字符集是 al32utf8
P
Peter Mortensen

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


P
Peter Mortensen

我的两分钱

如果不使用正确的数据类型,索引可能会失败: 在 SQL Server 中:当您在 VARCHAR 列上创建索引并将其呈现为 Unicode 字符串时,SQL Server 不会使用该索引。当您将 BigInt 呈现给包含 SmallInt 的索引列时,也会发生同样的事情。即使 BigInt 小到足以成为 SmallInt,SQL Server 也无法使用索引。相反,您没有这个问题(当向索引的 BigInt ot NVARCHAR 列提供 SmallInt 或 Ansi-Code 时)。不同 DBMS(数据库管理系统)之间的数据类型可能有所不同:要知道每个数据库的数据类型略有不同,而 VARCHAR 并不意味着在所有地方都相同。 SQL Server 有 VARCHAR 和 NVARCHAR,而 Apache/Derby 数据库只有 VARCHAR,而 VARCHAR 是 Unicode。


但可以肯定的是,如果您正确编写代码(即使用参数化查询等),那么第 1 点的风险较小。
d
dyslexicanaboko

Varchar(n)nvarchar(n) 之间的主要区别是:

https://i.stack.imgur.com/sAu3O.jpg

Varchar(可变长度、非 Unicode 字符数据)大小最大为 8000。

它是一种可变长度数据类型,用于存储非Unicode字符每个字符占用1个字节的空间

https://i.stack.imgur.com/l29wf.jpg

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

它是一种可变长度数据类型,用于存储 Unicode 字符。数据以 Unicode 编码存储。支持每种语言。 (例如阿拉伯语、德语、印地语等语言)


P
Peter Mortensen

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

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

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


A
Amar Anondo

varchar 仅用于 non-Unicode characters,而 nvarchar 用于 unicodenon-unicode 字符。下面给出了它们之间的其他一些区别。

VARCHAR 与 NVARCHAR

VARCHAR NVARCHAR 字符数据类型 可变长度、非 Unicode 字符 可变长度、Unicode 和非 Unicode 字符,例如日语、韩语和中文。最大长度 最多 8,000 个字符 最多 4,000 个字符 字符大小 每个字符占用 1 个字节 每个 Unicode/非 Unicode 字符占用 2 个字节 存储大小 实际长度(以字节为单位)的 2 倍实际长度(以字节为单位)是可变或可变长度列,如果实际数据总是小于容量由于仅存储,仅在需要 Unicode 支持(例如日文汉字或韩文字符)时使用。


M
Mike Spross

你是对的。 nvarchar 存储 Unicode 数据,而 varchar 存储单字节字符数据。除了您已经提到的存储差异(nvarchar 需要两倍于 varchar 的存储空间)之外,首选 nvarchar 而不是 varchar 的主要原因是国际化(即以其他语言存储字符串)。


V
Vijesh VP

nVarchar 将帮助您存储 Unicode 字符。如果您想存储本地化数据,这是要走的路。


P
Peter Mortensen

我会说,这取决于。

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

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


M
My Stack Overfloweth

虽然 NVARCHAR 存储 Unicode,但您应该考虑借助排序规则也可以使用 VARCHAR 并保存您的本地语言数据。

想象一下下面的场景。

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

但是,如果您想将数据传输到另一个数据库并查看正确的结果,您的目标数据库必须与目标数据库具有相同的排序规则,在此示例中为波斯语。

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

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

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


C
Community

如果使用单个字节来存储一个字符,则有 256 种可能的组合,从而可以保存 256 个不同的字符。排序规则是定义字符以及比较和排序它们的规则的模式。

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

统一码标准

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

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

非 Unicode(char、varchar 和 text)

Unicode(nchar、nvarchar 和 ntext)

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


R
Rafid

我查看了答案,许多人似乎建议使用 nvarchar 而不是 varchar,因为空间不再是问题,因此启用 Unicode 以获取少量额外存储空间并没有什么坏处。好吧,当您想在列上应用索引时,情况并非总是如此。 SQL Server 对可以索引的字段的大小有 900 个字节的限制。因此,如果您有 varchar(900),您仍然可以将其编入索引,但不能将 varchar(901)。使用 nvarchar,字符数减半,因此您最多可以索引 nvarchar(450)。因此,如果您确信不需要 nvarchar,我不建议您使用它。

一般来说,在数据库中,我建议坚持你需要的大小,因为你总是可以扩展的。例如,工作中的一位同事曾经认为将 nvarchar(max) 用于列没有什么坏处,因为我们在存储方面完全没有问题。后来,当我们尝试在该列上应用索引时,SQL Server 拒绝了。但是,如果他甚至从 varchar(5) 开始,我们可以稍后将其扩展为我们需要的,而不会出现需要我们执行现场迁移计划来解决此问题的问题。


A
Alexander Bartosh

Since SQL Server 2019 varchar columns support UTF-8 encoding.

因此,从现在开始,区别在于大小。

在转换为速度差异的数据库系统中。

更少的数据 = 更少的 IO + 更少的内存 = 总体上更快的速度。阅读上面的文章了解数字。

从现在开始使用 UTF8 中的 varchar!

仅当您有大量数据的字符在 2048 - 16383 和 16384 - 65535 范围内时 - 您必须测量


一个被严重低估的答案。我想知道有多少新数据库将使用 nvarchar,因为工程师只阅读了 2008 年的最佳答案。
P
Paul

我必须在这里说(我意识到我可能会敞开心扉!),但肯定是 NVARCHAR 真正更多有用的唯一时间(注意 更多!)比VARCHAR更多的是所有相关系统上的所有排序规则和数据库本身内的所有排序规则都相同......?如果不是,那么无论如何都必须进行排序规则转换,因此 VARCHARNVARCHAR 一样可行。

除此之外,一些数据库系统,例如 SQL Server (before 2012) 的页面大小约为。 8K。因此,如果您要存储未保存在 TEXTNTEXT 字段中的可搜索数据,则 VARCHAR 提供完整的 8k 空间,而 NVARCHAR 仅提供 4k(字节数翻倍,字节数翻倍)空间)。

我想,总而言之,两者的使用取决于:

项目或背景

基础设施

数据库系统


P
Peter Mortensen

关注 Difference Between Sql Server VARCHAR and NVARCHAR Data Type。在这里,您可以以非常具有描述性的方式看到。

一般来说,nvarchar 将数据存储为 Unicode,因此,如果您要在数据列中存储多语言数据(多于一种语言),则需要 N 变体。


这是一个非常有用的链接,但您的答案并不仅仅如此:一个链接。
ckuhn203 ,我不会告诉你看这个的
A
Allan F

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

Solomon Rutzky 信誉得分约为 33200,建议:不要总是使用 NVARCHAR。这是一种非常危险且通常代价高昂的态度/方法。

What are the main performance differences between varchar and nvarchar SQL Server data types?

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

这么高的名气,学习sql server的数据库开发者怎么选?

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

有关于性能的评论 pro/con nvarchar。

有评论 pro/con varchar 以提高性能。

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

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

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

我也在想我应该把相关代码表的数据类型与主中心表的数据类型相匹配。

我已经看到以前经验丰富的数据库开发人员在南澳大利亚政府的这个工作地点使用 varchar 列,其中表的行数将达到数百万或更多(并且在这些非常大的表),因此可能预期的数据行量成为此决定的一部分。


R
Rinoy Ashokan

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


like 和 = 的区别在于对 varchar 和 nvarchar 的支持
p
pavnis

varchar 适合存储非 unicode,这意味着有限的字符。虽然 nvarchar 是 varchar 的超集,所以除了我们可以使用 varchar 存储的字符之外,我们还可以存储更多而不忽略函数。

有人评论说现在存储/空间不是问题。即使空间对一个人来说不是问题,识别最佳数据类型也应该是一项要求。

这不仅仅是关于存储! “数据移动”,您会看到我的目标!