【问题标题】:LIKE ignores magic Unicode characterLIKE 忽略魔术 Unicode 字符
【发布时间】:2015-02-17 16:37:32
【问题描述】:

SQL Server 2008 R2

 create table #test (c1 nvarchar(5) not null)

  insert into #test values 
  (N'aaa'),
  (nchar(65533)),
  (N'bbb')

  select * from #test where c1 like N'%�%'
  select * from #test where c1 like N'%'+nchar(65533)+N'%'

结果是

c1
----
aaa
�
bbb

为什么?我在 MSDN 中没有找到关于这个案例的任何注释。

【问题讨论】:

  • 我已经用 sql fiddle 检查过一切都很好;sqlfiddle.com/#!3/fde76/3
  • 可能是你的collation 你的tempdb 数据库排序规则是什么?
  • Alsin,如果您有兴趣,我刚刚更新了我的答案以更清晰。

标签: sql-server tsql unicode sql-like


【解决方案1】:

该字符(以及许多其他字符,取决于所使用的排序规则版本)恰好没有定义排序权重。它实际上什么都不是。因此,无论您有 1 个实例还是 100 个实例,除了二进制排序规则之外,它对任何东西都是不可见的。意思是,以下WHERE 谓词:

LIKE N'%' +  NCHAR(0xFFFD) + N'%'

LIKE N'%' +  NCHAR(0xFFFD) +  NCHAR(0xFFFD) + N'%'

LIKE N'%' +  NCHAR(0xFFFD) +  NCHAR(0xFFFD) +  NCHAR(0xFFFD) + N'%'

等等,都等价于:

LIKE N'%%'

这就是返回所有 3 行的原因。

这并不意味着这个字符应该没有排序权重。它实际上在 Unicode 中被定义为具有权重,但出于某种原因,Microsoft 留下了相当多的字符,根本没有任何排序权重(尽管缺少排序权重的字符总数随着每个新的排序规则版本而减少,最新的是140 Collat​​ions 版本,随 SQL Server 2017 提供,仅适用于日语排序规则。

对于任何没有排序权重的字符,匹配它的唯一方法是使用二进制排序规则。二进制排序规则是以_BIN_BIN2 结尾的排序规则,但仅使用_BIN2 排序规则,因为它们可以正确排序,而旧的_BIN 排序规则则不能。例如:

SELECT * FROM #test WHERE c1 LIKE N'%�%' COLLATE Latin1_General_100_BIN2;

返回:

c1
----

此外,我使用以下内容进行了测试,它们返回了所有 3 行:

  • Latin1_General_CS_AS_KS_WS
  • Latin1_General_100_CS_AS_KS_WS_SC

所以,以下应该是好的:

  • Latin1_General_BIN2
  • Latin1_General_100_BIN2

此外,最好使用可用于您尝试使用的排序规则的最高排序规则版本。例如,使用Latin1_General_100_* 而不是Latin1_General_*,等等。使用以下查询查找您的实例上可用的排序规则:

SELECT col.*
FROM   sys.fn_helpcollations() col
ORDER BY col.[name];

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-12
    • 2011-01-29
    • 1970-01-01
    • 2012-07-14
    • 2012-04-08
    • 2019-08-03
    • 2013-02-08
    • 1970-01-01
    相关资源
    最近更新 更多