CONTAINS 谓词在 SQL Server 2008 中也不返回它应该返回的所有行

Posted

技术标签:

【中文标题】CONTAINS 谓词在 SQL Server 2008 中也不返回它应该返回的所有行【英文标题】:CONTAINS predicate in SQL Server 2008 nor returning all the rows that it should 【发布时间】:2012-08-20 15:35:54 【问题描述】:

背景

在 SQL Server 2008 中,我在名为boats 的表上的名为boatType 的列上使用全文索引。

boatType 字段包含一个以逗号分隔的船所属的boatType 列表。例如“multihull,trimaran,cruiser”。

执行搜索的我的 SQL 查询使用 CONTAINS 谓词,如下所示:

CONTAINS(boatType, '"multihull"')

问题

一切正常,直到最近我注意到没有返回特定行,但是,返回了具有完全相同数据的其他行。

短期解决方案

我尝试通过从boatType 列中删除全文索引来重建索引,然后重新添加它。我等待索引重新填充并解决了问题,即返回了所有预期的行。

什么是长期解决方案?

好的,所以问题在短期内得到解决,但如果这种情况发生一次,它可能会再次发生。

我假设(可能是错误的)全文索引上的“更改跟踪 = 自动”设置意味着对数据的任何更新都会导致索引的自动更新。

我没有设置任何人口计划,因为我假设如果我使用“更改跟踪 = 自动”,我不需要这样做。再说一次,也许我错了。

为了支持我的上述假设,添加到数据库或更改的新数据似乎确实会触发索引的更新,因为应该出现在搜索中的大多数行确实出现了。这只是少数。

这里最好做什么?

【问题讨论】:

也许更适合 DBA,因为这是一个非常集中的问题。 理想情况下(好吧,正确地)你不应该用逗号分隔的列表来表示船的类型。我有一个船型表和一个船和船型之间的多对多映射表。 我同意@pst。我有一个建议(这不是一个答案,所以我把它写成评论:为船类型创建一个查找表,然后创建一个连接表或用整数 ID 替换逗号分隔的文本并使用拆分函数因此您可以在该列上使用内部联接。 提示:我认为您不应该将船存储为逗号分隔。您最好通过创建表船(boatId,boatName,...,ownerId)来规范这种关系。虽然这不是您问题的答案。 我同意当前的表格结构并不完美。 【参考方案1】:

您不能依赖全文索引与索引数据的更新并行更新,来自MS Docs,

全文索引在后台更新,所以 传播的更改可能不会立即反映在索引中。

如果您要求船型搜索 100% 是最新的,请创建一个船型表和一个连接船型到船型的多对多映射表。

【讨论】:

谢谢 Will - 这听起来像是一个完美的解决方案,但需要一段时间才能实施,因为我的应用程序有很多部分需要更改。是否有一种临时解决方案可以使全文索引比现在更频繁地更新(它不必是最新的 - 即使晚了几个小时也可以 - 但是这个索引仍然没有更新的特殊问题数据更改后的一周),相比之下,完整的索引总体只需要几分钟。

以上是关于CONTAINS 谓词在 SQL Server 2008 中也不返回它应该返回的所有行的主要内容,如果未能解决你的问题,请参考以下文章

使用联接的 SQL Server 全文搜索无法按预期工作

SQL Server CONTAINS Predicate - 使用列值作为 <contains_condition>

在sql server中参数化全文查询

SQL contains查询语句

在 CloudKit 谓词中使用包含比较数组的 CONTAINS 或 ANY

sql server CONTAINS用法??