Hen*_*Lee 8 sql-server collation encoding unicode
Unicode代码点9619是一个叫“深色”字符:?(http://unicode-table.com/en/search/?q=9619)。
使用SQL_Latin1_General_CP1_CI_AS排序规则和 1252 代码页,我希望将该 Unicode 字符转换/转换为非 Unicode 数据类型会导致问号 ( ?),因为代码页 1252 似乎不包含此字符,这似乎是 SQL Server 的无法进行转换时的行为。
所以我的问题是:为什么 SQL Server 将此字符转换为 ASCII 代码 166,即“管道,垂直竖线”:¦?
SELECT NCHAR(9619), CAST(NCHAR(9619) AS CHAR(1)), ASCII(CAST(NCHAR(9619) AS CHAR(1)))
Run Code Online (Sandbox Code Playgroud)
为什么 SQL 将 Unicode 9619 转换为 ASCII 码 166?
SQL Server 在这里没有使用任何特殊的自定义逻辑;它使用标准操作系统服务来执行转换。
具体地,SQL Server的类型和表达服务(sqlTsEs)调用到OS程序WideCharToMultiByte在kernel32.dll。SQL Server 将输入参数设置为WideCharToMultiByte使例程执行“快速转换”。这比在不存在直接翻译时请求使用特定的默认字符要快。
快速翻译依赖于目标代码页为任何不匹配的字符执行最佳映射,如Martin Smith在对问题的评论中提供的链接中所述:
不同代码页的最佳匹配策略各不相同,并且没有详细记录。
当输入参数设置为快速翻译时,WideCharToMultiByte调用操作系统服务GetMBNoDefault( source )。在执行问题中指定的转换时检查 SQL Server 调用堆栈证实了这一点:

从 Unicode 数据转换为特定的代码页采用所谓的“最适合”策略(如@Paul的回答和@Martin 在对该问题的评论中指出的链接中所述)。根据.NET Framework中字符编码的MSDN页面:
最佳匹配映射是将 Unicode 数据编码为代码页数据的 Encoding 对象的默认行为...
但这些映射究竟是什么?该 MSDN 页面用于说明以下内容:
不同代码页的最佳匹配策略各不相同,并且没有详细记录。
然而,这并不完全正确。也许确定映射的“策略”没有完全记录。好的。但是,映射本身被记录在案,只是不在最容易找到的地方。
因此,感谢 Microsoft 将文档移至 GitHub,该页面现在声明如下(因为我更新了它?):
最佳匹配策略没有详细记录。但是,Unicode Consortium 的网站上记录了几个代码页。请查看该文件夹中的readme.txt文件,了解如何解释映射文件。
如果您转到以下 URL,您将看到一个包含多个文件的列表,每个文件都以其将 Unicode 字符映射到的代码页命名:
ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/
大多数文件最后更新(或至少放置在那里)是在 2006 年 10 月 4 日,其中一个是在 2012 年 3 月 14 日更新的。这些文件的第一部分将 ASCII 代码映射到等效的 Unicode 代码点。但是每个文件的第二部分将 Unicode 字符映射到它们的 ASCII“等价物”。
我编写了一个测试脚本,它使用代码页 1252 映射来检查 SQL Server 是否真正使用这些映射。这可以通过回答以下两个问题来确定:
?”字符?测试脚本太长无法放在这里,所以我把它贴在了 Pastebin 上:
运行脚本将显示上述第一个问题的答案是“是”(意味着所有提供的映射都得到遵守)。它还将显示第二个问题的答案是“否”(意思是,没有任何未映射的代码点转换为“未知”字符以外的任何内容)。因此,该映射文件非常准确:-)。
| 归档时间: |
|
| 查看次数: |
4470 次 |
| 最近记录: |