我有一个非常特殊的案例。我的 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
搜索其中包含 & 符号的字符串?最好不必将 & 符号转换为另一个安全字符?
最佳答案
您看到的奇怪行为很可能是由于 CONTAINS和 CONTAINSTABLE使用与号 ( &
) 字符等同于 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&sally
和 bob\&sally
的结果是一样的,在这两种情况下 bob
和 sally
是分开的,永远不会组合成一个完全匹配的字符串。
但是,r&f
和 r\&f
之间的结果并不相同。 r&f
仅被视为单个完全匹配的字符串,因为单独的 r
和 f
不是已知词。另一方面,添加反斜杠将两个字母分开,因为 \
是一个分词器,在这种情况下,您会得到 r
和 f
.
鉴于您在更新中声明您有“数据不一致,其中一个名称中带有“&”的品牌被修改为没有“&”,而另一个则没有”,我怀疑当您不添加 \
字符时,您会得到未修改的品牌(因为它是完整术语的精确匹配)。但是,当您确实添加\
字符时,您会得到被修改为具有&
的品牌已删除,因为您现在正在搜索两件作品,每件都与该品牌名称的一部分相匹配。
我会修复数据以使其保持一致:更新删除了 &
的品牌名称以将&符号放回原处。然后当人们使用 &
进行搜索时 如果不 添加额外的 \
,它将是完全匹配。这种行为将包含在数据中,并且不需要您添加代码来规避 FTS 的自然操作,这似乎是一种容易出错的方法。
关于sql-server - 使用 CONTAINSTABLE 转义 SQL Server 全文搜索查询中的符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39643231/