SQL Server:设置字符集(不是整理)

dot*_*hen 13 sql-server collation character-encoding character-set

在SQL Server中创建表时如何设置字段的默认字符集?在MySQL中,我们这样做:

CREATE TABLE tableName (
    name VARCHAR(128) CHARACTER SET utf8
) DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
Run Code Online (Sandbox Code Playgroud)

请注意,我在这里设置了两次字符集.这是多余的,我添加了两种方式来演示.

我还设置了排序规则,以证明排序规则是不同的.我不是要求设置整理.大多数 关于SQL Server中的字符集和编码的问题都通过整理来回答,这不是一回事.

Mar*_*ith 15

如BOL所述

每个SQL Server排序规则指定三个属性:

  • 用于Unicode数据类型(nchar,nvarchar和ntext)的排序顺序.排序顺序定义字符的排序顺序,以及在比较操作中计算字符的方式.
  • 用于非Unicode字符数据类型(char,varchar和text)的排序顺序.
  • 用于存储非Unicode字符数据的代码页.

以上引用来自2000个文档.另见2008年的链接.以下也证明了这一点.

DECLARE @T TABLE 
(
     code TINYINT PRIMARY KEY,
     Arabic_CS_AS CHAR(1) COLLATE Arabic_CS_AS NULL,
     Cyrillic_General_CS_AS CHAR(1) COLLATE Cyrillic_General_CS_AS NULL,
     Latin1_General_CS_AS CHAR(1) COLLATE Latin1_General_CS_AS NULL
);

INSERT INTO @T(code) VALUES (200),(201),(202),(203),(204),(205)

UPDATE @T 
  SET Arabic_CS_AS=CAST(code AS BINARY(1)),
      Cyrillic_General_CS_AS=CAST(code AS BINARY(1)),
      Latin1_General_CS_AS=CAST(code AS BINARY(1))

SELECT * 
FROM @T   
Run Code Online (Sandbox Code Playgroud)

结果

code Arabic_CS_AS Cyrillic_General_CS_AS Latin1_General_CS_AS
---- ------------ ---------------------- --------------------
200  ?            ?                      È
201  ?            ?                      É
202  ?            ?                      Ê
203  ?            ?                      Ë
204  ?            ?                      Ì
205  ?            ?                      Í
Run Code Online (Sandbox Code Playgroud)


Sol*_*zky 7

扩展@ Martin的答案:

如何在SQL Server中设置"字符集"取决于您使用的数据类型.如果您正在使用:

  • NVARCHAR,NCHARNTEXT(NTEXT已弃用,不应在SQL Server 2005中使用)都使用Unicode字符集,但无法更改.这些数据类型都编码为UTF-16 LE(Little Endian) - 一个16位编码,每个"字符"为2或4个字节 - 这也无法更改.对于这些数据类型,正在使用的排序规则仅影响区域设置(由排序规则的LCID确定),该区域设置确定用于排序和比较的规则集.

  • XMLN-prefixed类型一样,使用Unicode字符集并编码为UTF-16 LE(Little Endian),并且这些都不能更改.但与其他字符串数据类型不同,没有与XML数据关联的排序规则,因为无法对其进行排序或比较(至少在没有首先将其转换为NVARCHAR(MAX)[preferred]或VARCHAR(MAX))时也是如此.

  • VARCHAR,CHARTEXT(TEXT已弃用,不应在SQL Server 2005中使用)都是8位编码,每个"字符"为1或2个字节.字符集由与每个排序规则关联的代码页确定.排序和比较规则取决于所使用的排序规则的类型:

    • SQL Server归类:SQL_从SQL Server 2000 开始,这些名称都以名称开头并且已被弃用,但(不幸的是)现在仍然广泛使用.这些使用简单的规则表示为"SQL Server排序顺序"编号,该编号在description返回的字段中找到sys.fn_helpcollations().
    • Windows排序规则:这些都具有无法启动的名称SQL_.这些排序规则允许非Unicode字符串数据使用排序规则的LCID指示的Unicode排序和比较规则.

话虽这么说,要找出正在使用哪个字符集(for CHAR,VARCHARTEXT- 即非Unicode - 数据),请运行以下查询并密切关注该CodePage字段.该LCID字段指示用于排序的区域设置和N- 如果使用Windows排序规则的Unicode类型以及非Unicode类型的排序和比较规则:

SELECT *,
       COLLATIONPROPERTY(col.[name], 'CodePage') AS [CodePage],
       COLLATIONPROPERTY(col.[name], 'LCID') AS [LCID]
FROM   sys.fn_helpcollations() col
ORDER BY col.[name];
Run Code Online (Sandbox Code Playgroud)

可以通过代码页标识符的MSDN页面将代码页ID转换为更有意义的内容.


关于OP 对@ Martin答案的评论:

不幸的是,他们选择了误导性/不完整的术语"整理",明确指的是排序顺序:整理定义.

虽然微软在选择名称时可能做得更好,但不幸的是,对于诸如"编码","字符集","整理"等术语,整个行业都存在一般性的混淆.微软使用(或滥用) "整理"只是造成了大规模的混乱.但是,在这个问题中所显示的混乱也很明显,因为"utf8"特别不是字符集;-).

UTF-8是Unicode字符集的几种编码之一.UTF-16和UTF-32是另外两种编码.所有这三种编码都以不同的方式表示完全相同的Unicode字符集.查看MySQL字符集列表 - 11.1.10支持的字符集和排序规则 - "ucs2","utf8","utf8mb4","utf16","utf16le","utf32"字符集实际上不是字符集,每个se,但Unicode字符集的各种表示.但是,鉴于"字符集"和"编码"概念之间的重叠,很难不会产生这种混淆.该11.1.10.1 Unicode字符集页指出,"utf8mb4","UTF-16","utf16le应按"和"UTF32"的字符集是完整的Unicode字符集,而"UCS2"和"UTF-8"是Unicode字符集的子集,特别是前65,536个代码点(又名Basic Multilingual Plane(BMP)).

有关各种RDBMS的排序规则的更多信息,请参阅我对DBA.StackExchange上的以下问题的回答:

是否有任何DBMS都具有区分大小写和不区分重音的排序规则?


更新2018-10-02

虽然这还不是一个可行的选择,但SQL Server 2019在VARCHAR/ CHARdatatypes中引入了UTF-8的原生支持.目前有太多的bug用于它,但如果它们被修复,那么这是一些场景的选项.请参阅我的帖子," SQL Server 2019中的原生UTF-8支持:救世主还是假先知? ",详细分析了这一新功能.

  • 我觉得这比最初接受的解释更好。 (2认同)