sql-server - 使用 CONTAINSTABLE 转义 SQL Server 全文搜索查询中的符号

标签 sql-server tsql escaping full-text-search

我有一个非常特殊的案例。我的 ASP.NET 页面调用我们的存储过程,该过程对我们的数据库执行全文搜索查询。一些经常搜索的字符串包含一个符号,因为我们产品的一些品牌(也包括知名品牌)的名称中有一个 &

事实证明,在某些情况下我得不到任何结果除非我转义符号(\&),而在另一种情况下我得不到任何结果< em>仅当我转义 & 符号时。

我不知道这是否相关,但是(没有给出品牌名称)一个以 &b 结尾,另一个以 &c 结尾。

这些字符串(&b&c)有没有可能有它们自己的特殊含义?通过转义它们,我实际上是在将一个特殊的字符串传递给 T-SQL?

编辑

附加信息:经过进一步测试,我证明错误出在存储过程本身。使用 &\& 调用它会产生不同的结果。

我将尝试发布存储过程的选定部分。我不会全部发布,因为其中大部分都不是真正相关的。

vParamBuca 参数是造成问题的原因。值可以是 'word&letter'word\&letter

SET @ricercaA = '''FORMSOF(INFLECTIONAL,"' +
    REPLACE(LTRIM(RTRIM(@vParamBuca)),' ', '") AND FORMSOF(INFLECTIONAL,"') + '")'''

然后使用变量 @ricercaA 创建查询字符串:

[...]
FROM Products AS FT_TBL
LEFT OUTER JOIN CONTAINSTABLE (Products, Sign1, '+ @ricercaA + ') AS ColSign1_0 ON FT_TBL.ID = ColSign1_0.[KEY]
LEFT OUTER JOIN CONTAINSTABLE (Products, ManufacturerAdditionalText, '+ @ricercaA + ') AS ColManufacturerAdditionalText_0 ON FT_TBL.ID = ColManufacturerAdditionalText_0.[KEY]
LEFT OUTER JOIN CONTAINSTABLE (Products, ManufacturerForSearch, '+ @ricercaA + ') AS ColManufacturer_0 ON FT_TBL.ID = ColManufacturer_0.[KEY]
LEFT OUTER JOIN CONTAINSTABLE (Products, TuttaLaRiga, '+ @ricercaA + ') AS ColTuttaLaRiga_0 ON FT_TBL.ID = ColTuttaLaRiga_0.[KEY]
[...]

编辑 2

非常感谢@srutzky 为我指明了正确的方向!同时,我还发现了一个数据不一致的问题,其中一个品牌名称中带有&的品牌被修改为没有&,而另一个品牌则没有修改(最重要的是,我当前的问题是由以下原因引起的:过去某人所做的部分修复)。

不管怎样,回到正轨。现在我明白了 CONTAINSTABLE 函数中的 & 字符被视为逻辑与(非按位)。

我仍然需要一个解决方案。 This answer给出了一个对我不起作用的解决方案(条件和我的不一样)。我如何执行 CONTAINSTABLE 搜索其中包含 & 符号的字符串?最好不必将 & 符号转换为另一个安全字符?

最佳答案

您看到的奇怪行为很可能是由于 CONTAINSCONTAINSTABLE使用与号 ( & ) 字符等同于 AND 运算符的函数(均与 SQL Server 的全文搜索功能一起使用)。以下语句摘自 CONTAINS 的文档:

The ampersand symbol (&) may be used instead of the AND keyword to represent the AND operator.

没有提到它有任何转义字符(反斜杠通常不是 SQL 中的转义字符)。


更新

根据问题“编辑 2”中现在提供的信息以及其他研究,我会说您不需要逃避任何事情。似乎将搜索短语放在双引号中(作为使用 FORMSOF 的结果)将 & 视为文字或分词符,具体取决于值在 & 的两边。请尝试以下示例:

DECLARE @Term NVARCHAR(100);

SET @Term = N'bob&sally'; -- 48 rows
--SET @Term = N'bob\&sally'; -- 48 rows
--SET @Term = N'r&f'; -- 4 rows
--SET @Term = N'r\&f'; -- 24 rows

SET @Term = N'FORMSOF(INFLECTIONAL,"' + @Term + '")';

SELECT * FROM sys.dm_fts_parser(@Term, 1033, 0, 0);
SELECT * FROM sys.dm_fts_parser(@Term, 1033, 0, 1);
SELECT * FROM sys.dm_fts_parser(@Term, 1033, NULL, 0);
SELECT * FROM sys.dm_fts_parser(@Term, 1033, NULL, 1);

bob&sallybob\&sally 的结果是一样的,在这两种情况下 bobsally是分开的,永远不会组合成一个完全匹配的字符串。

但是,r&fr\&f 之间的结果并不相同。 r&f 仅被视为单个完全匹配的字符串,因为单独的 rf 不是已知词。另一方面,添加反斜杠将两个字母分开,因为 \ 是一个分词器,在这种情况下,您会得到 rf.

鉴于您在更新中声明您有“数据不一致,其中一个名称中带有“&”的品牌被修改为没有“&”,而另一个则没有”,我怀疑当您添加 \ 字符时,您会得到修改的品牌(因为它是完整术语的精确匹配)。但是,当您确实添加\ 字符时,您会得到修改为具有& 的品牌已删除,因为您现在正在搜索两件作品,每件都与该品牌名称的一部分相匹配。

我会修复数据以使其保持一致:更新删除了 & 的品牌名称以将&符号放回原处。然后当人们使用 & 进行搜索时 如果不 添加额外的 \,它将是完全匹配。这种行为将包含在数据中,并且不需要您添加代码来规避 FTS 的自然操作,这似乎是一种容易出错的方法。

关于sql-server - 使用 CONTAINSTABLE 转义 SQL Server 全文搜索查询中的符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39643231/

相关文章:

sql-server - SQL Server - 如何计算多个列中不同条目的数量?

SQL Server : Where condition based on the parameters

sql-server - 如何重置 SQL Server 2008 用户名和密码

php - 转义变量

sql - 在 Microsoft SQL Server 中比较日期的最佳方法是什么?

sql - 这些方法的优缺点是什么 SQL Server 繁琐的查询

c# - 读取 Entity Framework 字段的最大长度并分配给 Razor View 中的文本框

c# - 如何通过 LINQ to SQL 返回可变列长度

java - 如何在java中取消转义XML

.net - System.Uri 查询字符串中的文字与符号