SQL Server全文索引检索含小数点ArticleId前缀无结果问题
问题描述
你在Article表上创建了如下全文目录与全文索引:
create fulltext catalog [Article_Catalog] go create fulltext index on [Article] (ArticleId, ArticleIdTrimed, Designation, FlatVehicles, FlatCategories, FlatCriterias) key index [Article_id] on [Article_Catalog] with change_tracking = manual go alter fulltext index on [Article] start full population
对应存在ArticleId值为022.465的样例数据:
执行如下查询,当检索词设置为022.4时,无法返回任何结果:
-- Query Declare @q as varchar(50) = '022.4' declare @q2 varchar(50) set @q2 = isnull(@q, '') declare @ft varchar(50) set @ft = '"' + @q2 + '"' select a.DataSupplierId, a.SupplierId, a.ArticleId from containstable(article, ( ArticleId, ArticleIdTrimed ), @ft) ftx inner join article a on a.id = ftx.[key] order by ftx.[rank] desc
但将检索词改为完整值022.465、或是去掉小数点的022465时,查询都可以正常返回匹配结果。
问题原因
这个现象是SQL Server全文检索的两个默认规则共同导致的:
- 第一,你当前构造的检索词格式是
"检索内容",这种不带通配符的双引号写法在CONTAINSTABLE中是精确短语匹配逻辑,只会返回字段中完整出现和检索词完全一致的连续内容的记录,本身不支持前缀模糊匹配。 - 第二,SQL Server全文索引默认使用的断词器(Word Breaker)会将
.识别为单词分隔符:在生成倒排索引时,022.465会被拆分为两个相邻的独立索引token022和465,同时会生成去掉分隔符的无标点token022465;解析检索词时也会遵循同样的拆词规则。
当你检索"022.4"时,检索词会被拆为相邻的022和4两个token,而原数据中022相邻的后续token是465,和4不匹配,因此无法命中;检索"022.465"时,拆出的相邻token是022和465,和索引存储完全匹配,因此可以返回结果;检索022465时,和无标点的完整token匹配,也可以正常命中。
修复方案
- 如果需要实现前缀匹配,必须在双引号包裹的检索词末尾添加
*通配符,修改检索词构造逻辑即可:
这种写法下,检索词set @ft = '"' + @q2 + '*"'"022.4*"会被拆为022+前缀匹配4*的token规则,可以命中后续相邻的465,返回目标结果。 - 如果业务中
ArticleId这类编码里的小数点属于编码固定内容、不希望被断词器拆分,可以选择两种优化方式:- 建全文索引时,将这类编码字段的检索语言设置为中性语言(LCID为0),禁用针对特定语言的标点拆词逻辑,让带小数点的完整编码作为单个token存储
- 直接复用已有的
ArticleIdTrimed字段,查询前过滤掉检索词中的所有非数字/字母字符,匹配无标点的编码值,这种方式实现最简单,匹配准确率也最稳定。
内容的提问来源于stack exchange,提问作者Portekoi
相关产品推荐
相关产品推荐

