我们必须使用Unicode类型时有规则吗?
我已经看到,大多数欧洲语言(德语,意大利语,英语等等)在VARCHAR列的同一数据库中都可以。
我正在寻找类似的东西:
- 如果您有中文->使用NVARCHAR
- 如果您有德文和阿拉伯文->使用NVARCHAR
服务器/数据库的整理如何?
我不想像这里建议的那样始终使用NVARCHAR varchar和nvarchar SQL Server数据类型之间的主要性能差异是什么?
我们必须使用Unicode类型时有规则吗?
我已经看到,大多数欧洲语言(德语,意大利语,英语等等)在VARCHAR列的同一数据库中都可以。
我正在寻找类似的东西:
服务器/数据库的整理如何?
我不想像这里建议的那样始终使用NVARCHAR varchar和nvarchar SQL Server数据类型之间的主要性能差异是什么?
Answers:
最受欢迎的两个答案都是错误的。它应该与“存储不同/多种语言”无关。您可以ñ
使用仅通用varchar
字段和来支持西班牙语字符(如和英语)Latin1_General_CI_AS
COLLATION
,例如
简短版本只要由字段确定的,不支持所需的字符,
都应使用NVARCHAR
/ 。
另外,根据SQL Server版本的不同,您可以使用特定的,例如从SQL Server 2019开始可用的。在字段(或整个表/数据库)上设置此排序规则将用于存储和处理该字段上的数据,从而允许完全支持字符,因此也支持任何语言。NCHAR
ENCODING
COLLATION
COLLATIONs
Latin1_General_100_CI_AS_SC_UTF8
VARCHAR
UTF-8
ENCODING
UNICODE
要充分认识到:
要完全明白我做一下解释,这是强制性的,以拥有的概念UNICODE
,ENCODING
并COLLATION
在你的脑袋都非常清楚了。如果您不这样做,那么首先请看下面关于“什么是UNICODE,编码,集合和UTF-8,以及它们之间的关系”的简明扼要的解释以及随附的文档链接。另外,我在这里说的所有内容都是特定于的Microsoft SQL Server
,以及它如何存储和处理char
/nchar
和varchar
/nvarchar
字段中的数据。
假设我们要在MSSQL Server数据库上存储一个特殊的文本。可能是Instagram评论为“我喜欢stackoverflow!😍”。
即使是ASCII,也可以完美地支持纯英语部分,但是由于还有一个表情符号,它是UNICODE
标准中指定的字符,因此我们需要一个ENCODING
支持此Unicode字符的表情符号。
MSSQL Server使用COLLATION
,以确定哪些ENCODING
是在使用char
/ nchar
/ varchar
/nvarchar
场。因此,与很多人不同的COLLATION
是,这不仅与数据的排序和比较有关ENCODING
,而且与结果有关:如何存储我们的数据!
那么,我们如何知道我们的收藏所使用的编码是什么?有了这个:
SELECT COLLATIONPROPERTY( 'Latin1_General_CI_AI' , 'CodePage' ) AS [CodePage]
--returns 1252
这个简单的SQL返回Windows Code Page
了COLLATION
。AWindows Code Page
只不过是另一个映射到的映射ENCODINGs
。对于,Latin1_General_CI_AI
COLLATION
它返回映射到的Windows Code Page
代码。
因此,对于带有的列,此字段将使用来处理其数据,并且仅正确存储此编码支持的字符。1252
Windows-1252
ENCODING
varchar
Latin1_General_CI_AI
COLLATION
Windows-1252
ENCODING
如果检查Windows-1252的Windows-1252 ENCODING
规范字符列表,我们会发现该编码不支持我们的表情符号字符。如果我们仍然尝试:
好,那我们该如何解决呢?实际上,这取决于,那就好!
NCHAR
/NVARCHAR
在SQL Server 2019之前,我们所拥有的是NCHAR
andNVARCHAR
字段。有人说它们是UNICODE
田野。那是错的!。同样,它取决于字段的类型COLLATION
以及SQLServer的版本。微软的“ nchar和nvarchar(Transact-SQL)”文档完美地指定了:
从SQL Server 2012(11.x)开始,使用启用了补充字符(SC)的排序规则时,这些数据类型将存储完整范围的Unicode字符数据,并使用UTF-16字符编码。如果指定了非SC归类,则这些数据类型仅存储UCS-2字符编码支持的字符数据的子集。
换句话说,如果我们使用早于2012年的SQL Server(例如SQL Server 2008 R2),则ENCODING
这些字段的会使用UCS-2 ENCODING
支持的子集UNICODE
。但是,如果我们使用SQL Server 2012或更高版本,并且定义了COLLATION
已Supplementary Character
启用的,则在我们的字段中将使用UTF-16
ENCODING
完全支持的UNICODE
。
但是,还有更多!我们现在可以使用UTF-8了!
CHAR
/VARCHAR
从SQL Server 2019开始,我们可以使用CHAR
/VARCHAR
字段,并且仍然完全支持UNICODE
使用UTF-8
ENCODING
!!!
来自Microsoft的“ char和varchar(Transact-SQL)”文档:
从SQL Server 2019(15.x)开始,使用启用了UTF-8的排序规则时,这些数据类型存储完整范围的Unicode字符数据并使用UTF-8字符编码。如果指定了非UTF-8归类,则这些数据类型仅存储该归类的相应代码页支持的字符子集。
同样,换句话说,如果我们使用早于2019年的SQL Server,例如像SQL Server 2008 R2,则需要检查ENCODING
前面介绍的使用方法。但是,如果我们使用SQL Server 2019或更高版本,并定义一个COLLATION
like Latin1_General_100_CI_AS_SC_UTF8
,那么我们的字段将使用UTF-8
ENCODING
它是迄今为止支持所有UNICODE
字符的最常用和最有效的编码。
奖金信息:
关于OP关于“我发现大多数欧洲语言(德语,意大利语,英语,...)在VARCHAR列中的同一数据库中都可以使用”的意见,我认为很高兴知道为什么如此:
对于最常见的字段COLLATIONs
,如默认字段asLatin1_General_CI_AI
或SQL_Latin1_General_CP1_CI_AS
theENCODING
将Windows-1252
用于varchar
字段。如果我们看一下它的文档,我们可以看到它支持:
英文,爱尔兰文,意大利文,挪威文,葡萄牙文,西班牙文,瑞典文。加上德语,芬兰语和法语。和荷兰语,除了IJ字符
但是正如我之前说的,这与语言无关,与表情符号示例中显示的是您期望支持/存储的字符有关,或者诸如“锂电池的电阻为0.5Ω”之类的句子普通英语,以及希腊字母/字符“ omega”(以欧姆为单位的电阻符号),而不会正确处理Windows-1252
ENCODING
。
结论:
就是这样!使用char
/nchar
和varchar
/的时间nvarchar
取决于您要支持的字符,还取决于SQL Server的版本,SQL Server的版本将确定可用的字符,COLLATIONs
从而确定ENCODINGs
可用的字符。
什么是UNICODE,ENCODING,COLLATION和UTF-8,以及它们之间的相关性
注意:以下所有说明均为简化。请参考提供的文档链接以了解有关这些概念的所有详细信息。
UNICODE
-是一种标准,一种约定,旨在规范一个统一而有组织的表格中的所有字符。在此表中,每个字符都有一个唯一的数字。此数字通常称为字符code point
。
UNICODE不是编码!
ENCODING
-是字符和字节序列之间的映射。因此,编码用于将字符“转换”为字节,反之亦然,从字节转换为字符。其中最流行的是UTF-8
,ISO-8859-1
,Windows-1252
和ASCII
。您可以将其视为“转换表”(在此我进行了简化)。
COLLATION
-那很重要。甚至Microsoft的文档也没有像应该这样澄清。排序规则指定了如何对数据进行排序,比较和存储!。是的,我敢打赌您没想到最后一个,对吧!在归类SQL Server
决定过这将是ENCODING
用在特定char
/ nchar
/ varchar
/nvarchar
场。
ASCII ENCODING
-是最早的编码之一。它既是字符表(如的自己的小版本UNICODE
),也是其字节映射。因此,它不会将字节映射到UNICODE
,而是将字节映射到其自己的字符的表。此外,它始终仅使用7位,并支持128个不同的字符。它足以支持所有英文字母的大写和小写,数字,标点和其他一些有限的字符。ASCII的问题在于,由于当时它仅使用7位,并且几乎每台计算机都使用8位,因此还有另外128种可能的字符被“探索”,并且每个人都开始将“可用”字节映射到自己的字符表中,造成很多不同ENCODINGs
。
UTF-8 ENCODING
-这是另一个ENCODING
,是ENCODING
周围使用次数最多(如果不是最多)的游戏之一。它使用可变的字节宽度(根据规范,一个字符的长度可以从1到6个字节),并且完全支持所有UNICODE
字符。
Windows-1252 ENCODING
-也是最常用的工具之一ENCODING
,它已在SQL Server上广泛使用。它是固定大小的,因此每个字符始终为1个字节。它还支持多种语言的重音,但不支持所有现有的,也不支持UNICODE
。这就是为什么你varchar
有像一个普通的整理现场Latin1_General_CI_AS
支持á
,é
,ñ
即使它没有使用支持字符UNICODE
ENCODING
。
资源:
https : //blog.greglow.com/2019/07/25/sql-think-that-varchar-characters-if-so-think-again/
https://medium.com/@apiltamang/unicode-utf -8-and-ascii-encodings-made-easy-5bfbe3a1c45a
https://www.johndcook.com/blog/2019/09/09/how-utf-8-works/
https://www.w3.org/ International / questions / qa-what-is-encoding
https://en.wikipedia.org/wiki/List_of_Unicode_characters
https://www.fileformat.info/info/charset/windows-1252/list.htm
https:// docs .microsoft.com / zh-CN / sql / t-sql / data-types / char-and-varchar-transact-sql?view = sql-server-ver15
https://docs.microsoft.com/zh-CN/ sql / t-sql / data-types / nchar-and-nvarchar-transact-sql?view = sql-server-ver15
https://docs.microsoft.com/zh-CN/sql/t-sql/statements/windows-collation-name-transact-sql?view=sql-server-ver15
https://docs.microsoft.com/en -us / sql / t-sql / statements / sql-server-collation-name-transact-sql?view = sql-server-ver15
https://docs.microsoft.com/zh-CN/sql/relational-databases/ collations / collation-and-unicode-support?view = sql-server-ver15#SQL-collations
SQL Server默认字符编码
https://en.wikipedia.org/wiki/Windows_code_page
您要使用NVARCHAR的真正原因是,当同一列中有不同的语言时,您需要在T-SQL中寻址这些列而不解码,您希望能够在SSMS中“本地”查看数据,或者您想要标准化Unicode。
如果将数据库视为愚蠢的存储,则完全有可能在VARCHAR(例如UTF-8)中存储宽字符串和不同(甚至可变长度)编码。当您尝试编码和解码时,尤其是在不同行的代码页不同的情况下,就会出现问题。这也意味着,SQL Server将无法轻松地处理数据,以便在T-SQL内(可能可变)编码列上进行查询。
使用NVARCHAR避免了所有这些情况。
对于任何将用户输入的数据相对不受限制的列,我建议使用NVARCHAR。
我建议将VARCHAR用于任何自然键(例如,车牌,SSN,序列号,服务标签,订单号,机场呼号等),该列通常受标准或法律或公约的约束。也是用户输入的VARCHAR,非常受限制(例如电话号码)或代码(有效/关闭,是/否,M / F,M / S / D / W等)。绝对没有理由使用NVARCHAR。
因此,一个简单的规则是:
保证受约束时为VARCHAR否则为NVARCHAR
en-US
,但我的PC设置为fr-US
。
it is perfectly possible to store wide strings and different (even variable-length) encodings in VARCHAR (for instance UTF-8)
。您不能存储列编码不支持的字符。如果该列具有Latin1_General_CI_AS
排序规则,它将带有Windows-1252
encoling,因此您将无法存储表情符号,希腊字母Ω
或ẃ
示例字符。Windows-1252
该字节序列的编码中没有正确的映射。的ẃ
将是一个为存储?
,并且Ω
将被转换为O
。
您必须在必须存储多种语言的任何时候使用NVARCHAR。我相信您必须将其用于亚洲语言,但不要在上面引用我的意思。
如果您以俄语为例并将其存储在varchar中,这就是问题所在,只要定义正确的代码页就可以了。但是,假设您使用默认的英语sql安装,那么俄语字符将无法正确处理。如果您使用的是NVARCHAR(),则可以正确处理它们。
好吧,让我引述MSDN,也许我只是特定的,但是您不想在varcar列中存储一个以上的代码页,而您可以
当您处理存储在char,varchar,varchar(max)或text数据类型中的文本数据时,要考虑的最重要限制是系统只能验证单个代码页中的信息。(您可以存储来自多个代码页的数据,但是不建议这样做。)用于验证和存储数据的确切代码页取决于列的排序规则。如果尚未定义列级排序规则,则使用数据库的排序规则。要确定用于给定列的代码页,可以使用COLLATIONPROPERTY函数,如以下代码示例所示:
还有更多:
此示例说明了以下事实,例如格鲁吉亚语和北印度语等许多语言环境没有代码页,因为它们是仅Unicode归类。这些归类不适用于使用char,varchar或text数据类型的列
因此,格鲁吉亚语或北印度语确实需要存储为nvarchar。阿拉伯语也是一个问题:
您可能会遇到的另一个问题是,当代码页中未包含您希望支持的所有字符时,无法存储数据。在许多情况下,Windows都将特定的代码页视为“最合适”的代码页,这意味着无法保证您可以依靠该代码页来处理所有文本。它仅仅是最好的一种。阿拉伯文字就是一个例子:它支持多种语言,包括Bal路支语,柏柏尔文,波斯语,克什米尔语,哈萨克语,柯尔克孜语,普什图语,信德语,维吾尔语,乌尔都语等。除了Windows代码页1256中定义的阿拉伯语言外,所有这些语言都具有其他字符。如果您尝试将这些额外字符存储在具有阿拉伯语排序规则的非Unicode列中,
使用Unicode时要记住的一点是,尽管可以将不同的语言存储在单个列中,但只能使用单个排序规则进行排序。有些语言使用拉丁字符,但排序不像其他拉丁语言。口音是一个很好的例子,我无法记住这个例子,但是有一种东欧语言,其Y不像英语Y那样排序。然后是西班牙语ch,西班牙语用户期望在h之后进行排序。
总而言之,您在处理内部分类时必须处理的所有问题。我认为,从一开始就使用Unicode字符会更容易,避免额外的转换并节省空间。因此,我的发言较早。
乔什说:“ ....使用Unicode时要记住的一点是,尽管可以将不同的语言存储在单个列中,但只能使用单个排序规则进行排序。有些语言使用拉丁字符,但排序不像口音就是一个很好的例子,我无法说明这个例子,但是有一种东欧语言,其Y排序不像英语Y。在h之后。”
我是一个以西班牙语为母语的人,“ ch”不是字母,而是两个“ c”和“ h”,西班牙语字母像:abcdefghijklmn-opqrstuvwxyz我们不希望在“ h”之后出现“ ch”,而希望“ i”除了ñ或HTML“ñ”外,该字母与英语相同。
亚历克斯
如果有人在Mysql中遇到此问题,则无需将varchar更改为nvarchar,您只需将列的排序规则更改为utf8
TL; DR;
Unicode-(nchar,nvarchar和ntext)
非unicode-(char,varchar和text)。
SQL Server中的归类为数据提供排序规则,大小写和重音敏感性属性。与字符数据类型(例如char和varchar)一起使用的排序规则规定了代码页以及可以为该数据类型表示的相应字符。
假设您使用的是默认的SQL排序规则,SQL_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是将代码点映射到字符的标准。因为它旨在涵盖世界上所有语言的所有字符,所以不需要不同的代码页来处理不同的字符集。如果存储反映多种语言的字符数据,请始终使用Unicode数据类型(nchar,nvarchar和ntext),而不要使用非Unicode数据类型(char,varchar和text)。
否则,您的排序将很奇怪。
nchar
/在不同版本的SQL Server中nvarchar
使用不同encodings
的功能,例如UCS-2
不完全支持UNICODE
。
ñ
使用常见的varchar支持西班牙语和英语等西班牙语字符。