SQL Server 中的 Unicode 实现






3.63/5 (4投票s)
关于 SQL Server 中 Unicode 实现的信息。
起初,只有 ASCII
在 Windows/DOS 和 UNIX 系统上,最常用的 128 个字符都用一个 7 位序列来表示,称为字符的 ASCII 码。它们传统上存储为字节(8 位),即 7 位 ASCII 码加上一个前导零。这些字符包括字母、数字、标点符号以及一些不可打印的控制字符,如退格、制表符、回车符等。
对通用字符编码系统的需求
传统的字符集(如 ANSI 字母表)基于 8 位字符,称为字节。一个字节最多可以表示 256 种不同的值,因此可以表示 256 个字符。这足以表示西欧文字,如英语、法语或德语所使用的文字。然而,当涉及到日语或韩语等更复杂的语言时,256 个不同的字符是远远不够的。
因此,这些语言的用户开发了所谓的双字节字符集(DBCS)。在 DBCS 中,每个字符由一个或多个字节表示。字符编码指定如何解释字节值,以及一个字节是单个字符还是代表多字节字符的更大字节集的一部分。
不幸的是,对于给定的语言,存在许多不同的 DBCS 编码。更糟糕的是,不同的操作系统和不同的编程语言倾向于使用不同的 DBCS 编码。此外,由于字节解析操作,编程相对复杂。
Unicode 的目标是通过为每个字符使用多个字节来解决这个问题。因此,使用 Unicode,所有不同的字符都可以存储在一个字符串中。由于所有字符都具有固定宽度,编程的复杂性大大降低。
然后,Unicode 出现了
Unicode 是一项行业标准,它允许计算机一致地表示和处理用世界上任何一种书写系统表达的文本。Unicode 由大约 100,000 个字符组成。Unicode 联盟总部设在加利福尼亚州,其成员主要包括对文本处理标准感兴趣的计算机软件和硬件公司,如 Adobe Systems、Apple、HP、IBM、Microsoft、Xerox 等等。
Unicode 作为 UCS 和 UTF 的实现
已经为实现 Unicode 指定了几种机制。实现者选择哪种机制取决于可用的存储空间、源代码兼容性以及与其他系统的互操作性。
Unicode 定义了两种映射方法:Unicode 转换格式(UTF)编码和通用字符集(UCS)编码。编码将(可能是一个子集)Unicode 代码点的范围映射到某个固定大小范围内的值序列,称为“代码值”。通用字符集(UCS-2)格式是固定长度的字符字符串,其中每个字符由 2 个字节表示。
UTF 编码包括
- UTF-7 — 一种相对不受欢迎的 7 位编码,通常被认为是过时的(不是 Unicode 标准的一部分,而是 RFC)
- UTF-8 — 一种 8 位、可变宽度编码,最大限度地提高了与 ASCII 的兼容性。
- UTF-EBCDIC — 一种 8 位可变宽度编码,最大限度地提高了与 EBCDIC 的兼容性(不是 Unicode 标准的一部分)。
- UTF-16 — 一种 16 位、可变宽度编码。
- UTF-32 — 一种 32 位、固定宽度编码。
SQL Server 7.0 和 SQL Server 2000 使用不同的 Unicode 编码(UCS-2),并且不将 UTF-8 识别为有效的字符数据。
SQL Server 只支持 UCS-2 Unicode
在计算机中,字符由不同的二进制位模式表示,这些二进制位可以处于 ON 或 OFF 状态。一个字节有 8 位,这 8 位可以以 256 种不同的模式设置为 ON 和 OFF。因此,一个使用 1 个字节存储每个字符的程序可以通过将每个二进制位模式分配给一个字符来表示多达 256 个不同的字符。
排序规则
SQL Server 中字符字符串的物理存储由排序规则控制。排序规则指定表示每个字符的二进制位模式以及排序和比较字符的规则。SQL Server 支持在一个数据库中存储具有不同排序规则的对象。可以为 SQL Server 2000 的排序规则指定到列级别。表中的每一列都可以分配不同的排序规则。
Microsoft SQL Server 排序规则设置取决于安装类型。通常,选择一个支持您的站点最常用的 Microsoft Windows 系统区域设置的 SQL Server 排序规则。要在运行 Microsoft Windows 2000 的计算机上识别您的 Windows 系统区域设置,请在“控制面板”中单击“区域设置”,如果需要,再单击“常规”选项卡以显示当前的系统区域设置。
在大多数情况下,计算机运行的 Windows 系统区域设置与用户的语言要求相匹配,因此 Microsoft SQL Server 安装程序会自动检测 Windows 系统区域设置并选择适当的排序规则。
SQL Server 的 Unicode 支持
使用 1 个字节编码每个字符的数据类型存在一个问题,那就是该数据类型只能表示 256 个不同的字符。这导致对不同字母(如欧洲字母)需要多种编码规范(或代码页),而这些字母相对较少。对于像日文汉字或韩文韩文这样的拥有数千个字符的系统,也是无法处理的。
Unicode 规范通过使用两个字节编码每个字符来解决这个问题。2 个字节中有足够的不同模式(65,536 种)可以覆盖大多数常用商业语言。由于所有 Unicode 系统都一致地使用相同的二进制位模式来表示所有字符,因此在从一个系统移动到另一个系统时,不会出现字符转换错误的问题。通过在整个系统中使用 Unicode 数据类型,可以最大限度地减少字符转换问题。
Unicode 支持从 SQL Server 7.0 开始引入到 SQL Server 中。Microsoft SQL Server 只允许在 UCS-2 编码中存储 Unicode 数据。
数据类型
在 Microsoft SQL Server 中,以下数据类型支持 Unicode 数据
nchar
nvarchar
ntext
注意:这些数据类型前面的 n
前缀来自 SQL-92 标准中关于国家(Unicode)数据类型的规定。nchar
、nvarchar
和 ntext
的用法与 char
、varchar
和 text
分别相同,不同之处在于:
- Unicode 支持更广泛的字符
- 存储 Unicode 字符需要更多空间
nchar
和nvarchar
列的最大大小为 4,000 个字符,而不是char
和varchar
的 8,000 个字符- Unicode 常量前面加上
N
来指定:N'A Unicode string' - 所有 Unicode 数据都使用相同的 Unicode 代码页。排序规则不控制 Unicode 列使用的代码页,只控制比较规则和区分大小写等属性。
UNICODE 函数
它返回输入表达式的第一个字符的整数值,该值根据 Unicode 标准定义。UNICODE 函数具有以下语法
UNICODE ( 'ncharacter_expression' )
'ncharacter_expression'
是一个 nchar
或 nvarchar
表达式,返回值类型为 int
。
如何在 SQL Server 中存储 UTF-8 数据
以下选项可用于在 SQL Server 中存储 UTF-8 编码的数据。
与 UCS-2/UTF-8 之间的转换
有关此类转换的示例代码位于 Unicode 联盟的网站。有关将 UCS-2 转换为 UTF-8 的算法的高级描述可以在 Internet 请求注释文档 RFC2279 中找到。
在 Windows NT 或 Windows 2000 上,您可以使用 Win32 函数 MultiByteToWideChar
和 WideCharToMultiByte
,通过将常量 CP_UTF8
(65001) 作为第一个参数传递给这些函数,来与 UCS-2 进行 UTF-8 的相互转换。
使用 BINARY/VARBINARY/IMAGE 数据类型
使用 BINARY
/VARBINARY
/IMAGE
列在服务器上存储实际的 UTF-8 数据。将 UTF-8 数据存储在 SQL Server 中意味着您不能使用 SQL Server 来排序或查找这些值的范围,就好像这些数据是有效的字符数据一样。对包含 UTF-8 数据的列执行的操作,如 ORDER BY
、大于“>
”和小于“<
”的比较,以及内置的 SQL Server 字符串操作函数(如 SUBSTRING()
)等,将不会返回预期的结果。
但是,只要被比较的字符串在字节级别上是等效的,相等比较就可以工作。请注意,如果您在 SQL Server 中存储 UTF-8 数据,则不应使用字符列(CHAR
/NCHAR
/VARCHAR
等)。UTF-8 对 SQL Server 而言不是有效的字符数据,并且将非字符数据存储在字符列中,您可能会遇到问题,例如以下 Microsoft 知识库文章中讨论的问题:
- 155723 INF: SQL Server Truncation of a DBCS String
- 234748 PRB: SQL Server ODBC Driver Converts Language Events to Unicode
如果您正在考虑此选项,请记住,如果您需要从 Web 浏览器以外的任何应用程序(例如,从非 Web 的 ODBC 应用程序)访问存储在 SQL Server 中的 UTF-8 数据,您将需要在该应用程序中执行从 UTF-8 到 UCS-2 的转换。这是因为 ODBC、OLEDB、COM、Win32 API 调用、VB 和 C 运行时字符串操作函数不适用于 UTF-8 数据。这会将翻译的负担转移到另一个应用程序。