NLS 排序规则更改

受影响的平台

客户端 - Windows XP、Windows Vista、Windows 7
服务器 - Windows Server 2003、Windows Server 2008、Windows Server 2008 R2

功能影响

严重性 - 高
频率 - 低(很少有应用受到影响,但如果受影响,始终中断)

DESCRIPTION

国家语言支持(NLS)函数可帮助应用程序支持全球用户的不同语言和区域设置特定需求。 新的 Windows 版本几乎总是包括 NLS 更改。 此更改会影响排序规则和排序,从而会影响具有永久性索引的应用程序。

排序规则表有两个标识其版本(修订版)的数字:已定义的版本和 NLS 版本。 这两个版本都是 DWORD 值,由主版本和次要版本组成。 保留值的第一个字节,接下来的两个字节表示主版本,最后一个字节表示次要版本。 在十六进制术语中,模式为 0xRRMMMMmm,其中 R 等于保留、M 等于主要和 m 等于次要。 例如,主版本为 3 的次要版本 4 表示为 0x304。

对于主版本,一个或多个代码点发生更改,因此应用程序必须重新为所有数据编制索引,以确保比较是有效的。 对于次要版本,没有任何变化,只是增加了一些代码点。 对于这种类型的版本,应用程序只需使用以前不可排序的值重新为字符串编制索引。 总之,以下是版本号与特定于区域设置的异常表和默认表中的数据更改相关的含义:

NLSVersion Major – 更改了“异常情况”或区域特定表中的代码点
NLSVersion Minor – 在“例外”或区域特定表中添加了新的代码点
DefinedVersion Major - 更改了默认表中的代码点
DefinedVersion Minor – 在默认表中添加了新代码点

对已发布版本的版本号进行排序:

操作系统 版本 版本 (0xRRMMMMmm)
Windows XP RTM/SP1/SP2/SP3/... N/A - 无 GetNLSVersion() API
Windows Server 2003 RTM/SP1 0x00 0000 01
Windows Vista RTM/SP1 0x00 0405 00
Windows Server 2008 RTM 0x00 0501 00 / 0x00 5001 00
Windows 7 RTM 0x00060100

 

表现形式

具有未检查 NLS 版本并在版本更改时重新编制索引的持久性索引的应用程序(如数据库)将无法正确排序,或者可能无法提供请求的结果。

在用户界面中,列表(如字母、数字、字母数字、符号等)可能会错误排序。

解决方案

应用程序可以调用 GetNLSVersionEx (Windows Vista 或更高版本)或 GetNLSVersion (在 Windows Vista 之前)来检索排序规则表的已定义版本和 NLS 版本。

  • GetNLSVersionEx:

针对名称指定的区域,检索指定 NLS 功能的当前版本信息
此函数允许 Active Directory 等应用程序确定 NLS 更改是否影响用于特定索引表的区域设置。 如果没有,则无需重新为表编制索引。 有关详细信息,请参阅“处理区域和语言信息”。
此函数支持自定义区域设置。 如果 lpLocaleName 指定补充区域设置,则检索的数据是与该补充区域设置关联的排序规则顺序的正确数据。

注意: Windows Vista 之前的 Windows 版本不支持 GetNLSVersionEx

  • GetNLSVersion(用于在 Windows Vista 之前的 Windows 版本上运行的应用程序):

针对标识符指定的区域,检索指定 NLS 功能的当前版本信息
此函数允许 Active Directory 等应用程序确定 NLS 更改是否影响用于特定索引表的区域设置标识符。 如果没有,则无需重新为表编制索引。 有关详细信息,请参阅“处理区域和语言信息”。
注意:此函数仅检索标识符所指定的区域相关信息。 GetNLSVersionEx 函数支持其他区域设置、功能和 RFC 4646 名称。 但是,Windows Vista 之前的 Windows 版本不支持 GetNLSVersionEx
仅打算在 Windows Vista 及更高版本上运行的应用程序应优先考虑使用 GetNLSVersionEx 而不是此函数。 GetNLSVersionEx 为补充区域提供了良好的支持。

兼容性测试

判断排序规则版本是否已更改(即需要重新编制索引)的步骤:

  • 在对数据建立原始索引时,使用 GetNLSVersionEx() 获取 NLSVERSIONINFOEX 结构。

  • 将以下属性与索引一起存储以标识版本: NLSVERSIONINFOEX.dwNLSVersionNLSVERSIONINFOEX.dwDefinedVersion – 这两个属性共同指定所使用的排序表的版本。
    NLSVERSIONINFOEX.dwEffectiveId - 这将指定排序的有效区域。 自定义区域设置会指向内置区域的排序。

  • 使用索引时,使用 GetNlsVersionEx() 来发现数据的版本。

  • 如果三个属性中的任何一个已更改,则所使用的排序数据可能会返回不同的结果,并且可能找不到记录的任何索引。

  • 如果你知道你的数据不包含无效的 Unicode 码位(也就是说,通过调用 IsNLSDefinedString()返回 TRUE 的所有字符串),那么,如果只有 dwNLSVersiondwDefinedVersion 的低字节发生了更改(上述次要版本),你可以认为它们是相同的。