在 SQL Server 2019 中比较 Unicode 字符串文字时使用的排序规则是什么?

QFi*_*ast 3 sql-server collation encoding sql-server-2019

我的理解是,比较 Unicode 字符串文字的排序规则是由数据库排序规则决定的。

\n

我的数据库正在使用SQL_Latin1_General_CP1_CI_AS排序规则。

\n

当我将 N\'\xc3\x9f\' 与 \'ss\' 进行比较时,我预计比较会失败。但事实并非如此。我正在尝试找出原因。这是复制品:

\n
    set nocount on \n    go\n    use tempdb\n    go\n    \n    SELECT \n       @@version as SqlServerVersion,\n       CONVERT(nvarchar(128), SERVERPROPERTY(\'collation\')) as SqlServerCollation,\n     DB_NAME() AS DatabaseName\n    ,DATABASEPROPERTYEX(DB_NAME(), \'Collation\') AS CollationUsedBySQLServerDatabase\n    GO\n    declare @ss varchar(255) = \'ss\'\n    declare @Nscharfess nvarchar(255) = N\'\xc3\x9f\'\n    declare @scharfess varchar(255) = \'\xc3\x9f\'\n    \n    select case  when @Nscharfess   = @ss then \'Unicode : Strings match\' else \'Unicode : Strings do not match\' end,\n            case when @scharfess    = @ss then \'SQL_Latin1_General_CP1_CI_AS : Strings match\' else \'SQL_Latin1_General_CP1_CI_AS : Strings do not match\' end\n
Run Code Online (Sandbox Code Playgroud)\n

输出:

\n
    set nocount on \n    go\n    use tempdb\n    go\n    \n    SELECT \n       @@version as SqlServerVersion,\n       CONVERT(nvarchar(128), SERVERPROPERTY(\'collation\')) as SqlServerCollation,\n     DB_NAME() AS DatabaseName\n    ,DATABASEPROPERTYEX(DB_NAME(), \'Collation\') AS CollationUsedBySQLServerDatabase\n    GO\n    declare @ss varchar(255) = \'ss\'\n    declare @Nscharfess nvarchar(255) = N\'\xc3\x9f\'\n    declare @scharfess varchar(255) = \'\xc3\x9f\'\n    \n    select case  when @Nscharfess   = @ss then \'Unicode : Strings match\' else \'Unicode : Strings do not match\' end,\n            case when @scharfess    = @ss then \'SQL_Latin1_General_CP1_CI_AS : Strings match\' else \'SQL_Latin1_General_CP1_CI_AS : Strings do not match\' end\n
Run Code Online (Sandbox Code Playgroud)\n
\n

我希望 \'\xc3\x9f\' 和 \'ss\' 匹配,但如果我的数据库位于 SQL_Latin1_General_CP1_CI_AS,则不会匹配。我想检查一下我的理解是否存在差距,目前的理解是“对于 Nvarchar() 或 Nchar() 数据类型,SQL Server 从数据库设置中获取排序规则”。这意味着“我的数据库位于 SQL_Latin1_General_CP1_CI_AS,因此比较应该失败。如果成功,SQL Server 使用什么排序规则?为什么?

\n

Sol*_*zky 7

\n

我的理解是,比较 Unicode 字符串文字的排序规则是由数据库排序规则决定的。

\n
\n

是的,这是正确的。事实上,本地数据库的默认排序规则用于比较 Unicode 和非 Unicode 字符串文字(以及变量/参数)。

\n
\n

当我将 N\'\xc3\x9f\' 与 \'ss\' 进行比较时,我预计比较会失败。但事实并非如此。

\n
\n

两次比较的区别在于,当使用 SQL Server 排序规则(即名称以 开头的排序规则SQL_时,非 Unicode 比较使用 Unicode 比较规则,而如果您使用 Windows 排序规则,它将使用Unicode 和非 Unicode 比较的比较规则相同。

\n

在比较或排序非 Unicode 数据时,SQL Server 排序规则使用一组过时的规则,这些规则比 Unicode 规则的限制要大得多。这些过时的规则不应设定期望(除非您的用例需要旧行为)。

\n

这就是为什么首选使用较新的 Windows 排序规则(非常不幸的是,SQL Server仍然使用SQL_Latin1_General_CP1_CI_AS美国英语语言环境的操作系统上新安装的默认排序规则)。

\n

要查看示例数据的差异,只需将以下内容添加到第二条SELECT语句中:

\n
,\n            case when @scharfess  = @ss COLLATE Latin1_General_CI_AS \n                 then \'Latin1_General_CI_AS : Strings match\'\n                 else \'Latin1_General_CI_AS : Strings do not match\'\n            end;\n
Run Code Online (Sandbox Code Playgroud)\n

你会得到回报:

\n
Latin1_General_CI_AS : Strings match\n
Run Code Online (Sandbox Code Playgroud)\n

即使使用非 Unicode 字符串,过时行为与 Unicode 行为之间的另一个区别可以在以下示例中看到,该示例仅返回一行“2”:

\n
Latin1_General_CI_AS : Strings match\n
Run Code Online (Sandbox Code Playgroud)\n