【发布时间】:2019-09-07 09:26:23
【问题描述】:
我注意到 SQL Server 上的 PATINDEX(我使用的是 2016)给出了奇怪的结果。 我怀疑它与排序规则和字符集有关。
我正在尝试使用 PATINDEX 获取第一个空格或连字符的索引。
在具有默认排序规则 SQL_Latin1_General_CP1_CI_AS 的数据库上,我得到预期结果 0(未找到):
select PATINDEX('%[ -]%', 'ABC') -- returns 0
select PATINDEX('%[ -]%', N'ABC') -- returns 0
select PATINDEX('%[- ]%', N'ABC') -- returns 0
但是,在排序为 Latin1_General_100_BIN 的数据库中,我得到了一个意外的错误结果,表明在索引 1 处发现了空格或连字符:
select PATINDEX('%[ -]%', 'ABC') -- returns 0
select PATINDEX('%[ -]%', N'ABC') -- returns 1 (WRONG!)
select PATINDEX('%[- ]%', N'ABC') -- returns 0
总之,我注意到这个明显错误的结果是:
- 排序Latin1_General_100_BIN
- 搜索 unicode 字符串
- 模式中的连字符出现在最后。
我见过其他类似的问题,但它们并没有解决完全相同的情况,尤其是为什么模式适用于一种排序规则而不适用于其他排序规则,并且适用于非 unicode 字符串而不适用于 unicode 字符串。 我见过patindex t-sql special characters,它表示除第一个位置之外的任何位置的“-”字符都是 LIKE 和 PATINDEX 的范围规范(尽管我在SQL Server PATINDEX 或Wildcard 文档中没有看到它)。仍然没有解释为什么它在某些配置中有效,而在其他配置中无效。
为什么会有如此不同的 PATINDEX 和明显错误的结果?
【问题讨论】:
-
我确实在 2012 年将其报告为错误。它被关闭为“无法修复”。原链接connect.microsoft.com/SQLServer/feedback/details/742841/…但貌似在返程机中不存在这个
-
响应是 来自 SQL Server 团队的问候。感谢您写信给微软。我们非常重视您的反馈。我们能够重现您提到的错误。但是,repro 中提到的所有模式都是无效的,因为 SQL Server 将“-”视为特殊字符并需要一个开始和结束范围。理想情况下,这些无效模式应返回 NULL,但当前行为不会这样做。我们将考虑修改行为以供将来发布。再次感谢您提供反馈并使 SQL Server 成为最出色的数据库服务器。问候阿蒂什·阿格拉瓦尔
-
我认为行为实际上在未来版本中被修改的可能性非常接近于零(尤其是它永远返回
NULL!),因为它可能会破坏现有的系统,这些系统正是指望这种不直观的行为发生,而它的解决方法相当简单(如果不一定明显要完全正确)。以防万一自 2012 年以来没有发生任何事情的事实已经不是一个很好的指标,可以让你屏住呼吸。 -
是的 - 可以将适当的正则表达式支持作为本机函数实现,这样我们就可以忘记
PATINDEX -
感谢大家的回复,非常感谢。在所有这些中,我认为 Martin Smith 的 cmets 是最准确的,因为它们表明 Microsoft 认识到这是一个错误。即连字符是一个特殊字符,不作为单独的字符进行搜索。因此,在 PATINDEX 中所有这些连字符的使用都应该返回一个错误,而不是它们经常出现的巧合结果。
标签: sql-server tsql patindex