为什么在Microsoft SQL Server中我们需要在字符串前放置N?


34

我正在学习T-SQL。从我看到的示例中,要在varchar()单元格中插入文本,我只能编写要插入的字符串,但是对于nvarchar()单元格,每个示例都在字符串前加上字母N。

我在具有nvarchar()行的表上尝试了以下查询,并且工作正常,因此不需要前缀N:

insert into [TableName] values ('Hello', 'World')

为什么在我看到的每个示例中,字符串都以N为前缀?

使用此前缀的利弊是什么?


文字字符串不是只需要N吗?
Wayne In Yak 2012年

波兰语是一种非拉丁语的语言?
Heckflosse_230

2
N表示“国家”,如“国家字符”中所述,请参见等效ANSI SQL数据类型
ErikE 2014年

我同意这个问题,到目前为止,没有人回答过,AFAICT。也许可以这样重申:“ 当我的字符串文字为ASCII时,为什么让SQL隐式将我转换VARCHARNVARCHAR我?
binki 2014年

这个问题已经在这里被问到并得到回答:varchar和nvarchar有什么区别?

Answers:


27

NVarchar用于Unicode。如果您的数据库未存储多语言数据,则可以继续使用Varchar。举个例子:N'abc'简单地将您的字符串转换为unicode。


2
为什么您不必在前面加上U而不是N?
Attila Kun

ü可能会混淆为无符号的猜测
JB国王

U&'abc'是指定Unicode字符串的正确方法。请参见SQL 2003 BNF
ceving

2
N实际上代表“国家语言字符”集。
Mike Bovenlander '18

23

默认情况下,SQL Server 对varchar使用Windows-1252字符代码。它包含基于拉丁语的语言(英语,德语,法语等)的大多数字符,但不包含基于非拉丁语的语言(波兰语,俄语等)的字符。如@Pieter B所述,nvarchar用于解决该问题,因为它用于Unicode,其中包含那些丢失的字符。这是有代价的,存储nvarchar所需的空间是varchar的两倍。

将N放在字符串前面可确保在将这些字符放入nvarchar列之前将其转换为Unicode。大多数时候,您可以将N保留下来,但我不建议这样做。安全比后悔好得多。


3
需要说明的是:“默认情况下” SQL Server使用与Varchar字段的排序规则相对应的编码,该编码在创建字段时可以重写,通常基于实例的默认排序规则。您的实例的默认排序规则可以在安装时设置,但通常对应于系统默认语言环境的CP_ACP。在美式英语计算机上将是Windows 1252,而在具有日语系统区域设置的计算机上将是932,在俄文计算机上将是1251,等等。故事的寓意是什么?使用NVarchar :)
JasonTrue 2012年

1
到目前为止,这是解决“为什么在文字字符串上使用N前缀,因为SQL会隐式转码?”的唯一答案。其他答案都是针对不同的问题“ nvarchar与varchar有什么区别?”
廷博

18

因为与其他RDBMS相比,MS SQL Server对UTF-8的支持较差。

MS SQL Server遵循Windows本身使用的约定,即“窄”字符串(char使用C ++ CHARVARCHARSQL)在旧版“代码页” 中编码。代码页的问题是它们的字符数有限(大多数是单字节编码,这将报告格式限制为256个字符),并且围绕一种语言(或具有相似字母的语言组)进行设计。这使得难以存储多语言数据。例如,您不能同时存储俄语和希伯来语数据,因为俄语使用代码页1251,而希伯来语使用代码页1255

Unicode通过使用一个单一的巨型编码字符集解决了这个问题,该字符集可以容纳超过一百万个字符,足以代表世界上的每种语言。有几种Unicode编码方案。出于历史原因,Microsoft更喜欢使用UTF-16。因为UTF-16将字符串表示为16位代码单元的序列,而不是传统的8位,所以需要单独的字符类型。在MSVC ++中,这是。在MS SQL中,它是或。该代表“国家”,这似乎倒退到我,因为Unicode是约 -nationalization,但是这是ISO的术语。wchar_tNCHARNVARCHARN

其他SQL实现使您可以将UTF-8文本存储在VARCHAR列中。UTF-8是一种可变长度(每个字符1-4字节)的编码,针对您的数据主要在基本拉丁语范围(表示为每个字符与ASCII相同的1个字节)的情况下进行了优化,但可以表示任何Unicode字符。因此,您可以避免bwalk2895提到的“两倍大的空间”问题。

不幸的是,MS SQL Server 不支持UTF-8VARCHAR,因此您必须改用UTF-16(并浪费ASCII文本的空间),使用非Unicode代码页(并失去表示外来字符的能力),或将UTF-8存储在BINARY列中(并处理SQL 字符串函数无法正常工作等不便之处,或者必须在GUI DB管理器中将数据作为十六进制转储查看)。


1
在SQL Server 2012之前的版本中,它们使用UCS-2编码进行编码,该编码严格为2byte。在较新的版本中,他们使用的是UTF-16,它的可变长度映射到每个字符4个字节(类似于UTF-8,但从2个字节开始)。
j123b567
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.