什么时候我们必须在SQL Server中使用NVARCHAR / NCHAR而不是VARCHAR / CHAR?

当我们必须使用Unicodetypes时,是否有规则?

我已经看到,大多数欧洲语言(德语,意大利语,英语,…)在VARCHAR列的同一个数据库中都很好。

我正在寻找像这样的东西:

  1. 如果你有中文 – >使用NVARCHAR
  2. 如果你有德语和阿拉伯语 – >使用NVARCHAR

怎么样的服务器/数据库的整理?

我不想像这里所提到的那样总是使用NVARCHAR varchar和nvarchar SQL Server数据types之间的主要性能区别是什么?

你想使用NVARCHAR的真正原因是当你在同一列中有不同的语言时,你需要在T-SQL中寻址列而不解码,你希望能够在SSMS中“本地”地看到数据,或者你想在Unicode上进行标准化。

如果将数据库视为哑存储,则可以在VARCHAR(例如UTF-8)中存储宽string和不同(甚至可变长度)的编码。 问题出现在您尝试编码和解码时,尤其是在不同行的代码页不同的情况下。 这也意味着SQL Server将无法轻松处理数据,以便在(可能变化的)编码列上查询T-SQL。

使用NVARCHAR可以避免这一切。

我会build议NVARCHAR的任何列将有用户input的数据,它是相对不受限制的。

我会build议VARCHAR的任何列是一个自然的关键(如车牌照,SSN,序列号,服务标签,订单号码,机场呼号等)或用户input,但非常约束(如电话号码)或代码(ACTIVE / CLOSED,Y / N,M / F,M / S / D / W等)。 这些绝对没有理由使用NVARCHAR。

所以对于一个简单的规则:

否则保证被限制为NVARCHAR的VARCHAR

您必须在任何时候使用NVARCHAR来存储多种语言。 我相信你必须把它用于亚洲语言,但不要引用我的话。

如果以俄语为例,并将其存储在一个varchar中,问题就出在这里,只要您定义了正确的代码页就可以了。 但是让我们说你使用默认的英文SQL安装,那么俄文字符将不会被正确处理。 如果你使用的是NVARCHAR(),它们将被正确处理。

编辑

好吧,让我引用MSDN ,也许我是特定的,但你不想多存储一个代码页在varcar列,而你可以不应该

处理存储在char,varchar,varchar(max)或text数据types中的文本数据时,需要考虑的最重要的限制是只有来自单个代码页的信息才能被系统validation。 (您可以存储多个代码页中的数据,但不build议这样做。)用于validation和存储数据的确切代码页取决于列的sorting规则。 如果列级别的sorting规则尚未定义,则使用数据库的sorting规则。 要确定用于给定列的代码页,可以使用COLLATIONPROPERTY函数,如以下代码示例所示:

还有一些:

这个例子说明了许多语言环境(如格鲁吉亚语和印地语)没有代码页,因为它们是仅Unicode的sorting规则。 这些sorting规则不适用于使用char,varchar或text数据types的列

所以格鲁吉亚语或印地语确实需要存储为nvarchar。 阿拉伯语也是一个问题:

您可能遇到的另一个问题是,如果您希望支持的所有字符都不包含在代码页中,则无法存储数据。 在很多情况下,Windows认为特定的代码页是“最合适的”代码页,这意味着不能保证您可以依靠代码页来处理所有文本; 它只是最好的一个。 这方面的例子是阿拉伯文:它支持多种语言,包括俾路支语,柏柏尔语,波斯语,克什米尔语,哈萨克语,柯尔克孜语,普什图语,信德人,维吾尔语,乌尔都语等。 所有这些语言都具有除Windows代码页1256中定义的阿拉伯语之外的其他字符。如果尝试将这些额外字符存储在具有阿拉伯归类的非Unicode列中,则这些字符将转换为问号。

在使用Unicode时要注意的一点是,虽然可以在单个列中存储不同的语言,但只能使用单个sorting规则进行sorting。 有一些使用拉丁字符的语言,但不能像其他拉丁语言那样sorting。 口音就是一个很好的例子,我不记得这个例子,但是有一个东欧语言,其Y不像英语Y那样sorting。然后是西class牙语用户在h之后sorting的西class牙语。

总而言之,在处理内部化问题时,你必须处理所有的问题。 我认为从一开始就使用Unicode字符比较容易,避免额外的转换,并且占用空间。 因此,我先前的发言。

希腊语需要N列types的UTF-8:αβγ;)

Josh说:“…当你使用Unicode时,要记住一些东西,尽pipe你可以在一个列中存储不同的语言,你只能使用单个sorting规则进行sorting。有些语言使用拉丁字符,但是不能sorting其他的拉丁语言,口音就是一个很好的例子,我不记得这个例子,但是有一个东欧语言,其Y不像英语Y那样sorting。然后是西class牙语用户,之后“。

我是一个西class牙语母语的人,“ch”不是一个字母,而是两个“c”和“h”,西class牙字母表是这样的:abcdefghijklmn-opqrstuvwxyz我们并不期待“h”之后的“ch”,而是“i”除英文外,英文字母与英文相同,或用HTML“&ntilde”代替

亚历克斯

TL; DR;
Unicode – (nchar,nvarchar和ntext)
非Unicode – (char,varchar和文本)。

来自MSDN

SQL Server中的sorting规则为数据提供sorting规则,大小写和口音敏感性属性。 与字符数据types(如char和varchar)一起使用的sorting规定了可以为该数据types表示的代码页和相应的字符。

假设你正在使用默认的SQLsortingSQL_Latin1_General_CP1_CI_AS那么下面的脚本应该打印出你可以放在VARCHAR所有符号,因为如果你没有在列表中看到它,它将使用一个字节来存储一个字符(总计256) – 你需要NVARCHAR

 declare @i int = 0; while (@i < 256) begin print cast(@i as varchar(3)) + ' '+ char(@i) collate SQL_Latin1_General_CP1_CI_AS print cast(@i as varchar(3)) + ' '+ char(@i) collate Japanese_90_CI_AS set @i = @i+1; end 

如果改变整理让日本人说,你会注意到,所有的怪异的欧洲字母变成正常的,一些符号变成? 分数。

Unicode是将代码点映射到字符的标准。 因为它的devise涵盖了世界上所有语言的所有字符,所以不需要不同的代码页来处理不同的字符集。 如果存储反映多种语言的字符数据,请始终使用Unicode数据types(nchar,nvarchar和ntext),而不要使用非Unicode数据types(char,varchar和text)。

否则你的sorting会变得奇怪。