我有一个非常奇怪的案例。我的ASP.NET页面调用我们的存储过程,在我们的数据库上执行全文搜索查询。一些常用的字符串包括&符号,因为我们的产品中的一些品牌(知名品牌)的名字中都有&
。
事实证明,在某种情况下,我没有得到任何结果除非我逃脱&符号(\&
),而在某些其他情况下我只得到我逃脱了&符号。
我不知道这是否相关,但是(没有给出品牌名称)一个以&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
字符被视为逻辑AND(非按位)。
我仍然需要一个解决方案。 This answer给出了一个对我不起作用的解决方案(条件与我的不同)。如何在CONTAINSTABLE
搜索带有&符号的字符串?最好不必将&符号转换为另一个安全字符?
答案 0 :(得分:2)
您看到的奇怪行为很可能是由于CONTAINS和CONTAINSTABLE函数(均与SQL Server的全文搜索功能一起使用)使用&符号{{1} })字符等同于&
运算符。以下声明摘自AND
的文档:
可以使用&符号(&)代替AND关键字来表示AND运算符。
没有提到它有任何转义字符(并且反斜杠通常不是SQL中的转义字符)。
<强>更新强>
根据&#34;编辑2&#34;中提供的信息问题和其他研究,我会说你不需要逃避任何事情。似乎将搜索短语放在双引号中(作为使用CONTAINS
的结果)将FORMSOF
视为字面值或断字符,具体取决于{两边的值} {1}}。请尝试以下示例:
&
&
和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
都是分开的,并且永远不会合并为一个完全匹配的字符串。< / p>
然而,bob
和sally
之间的结果并不相同。 r&f
仅被视为单个完全匹配字符串,因为仅r\&f
和r&f
不是已知单词。另一方面,添加反斜杠会分隔两个字母,因为r
是一个断字符,在这种情况下,您同时获得f
和\
。
鉴于您在更新中声明您有&#34; 数据不一致,其中一个品牌带有&#34;&amp;&#34;在其名称中被修改为不具有&#34;&amp;&#34;,而另一个不是&#34;,我怀疑当你做不添加r
字符,即可获得未修改的品牌(因为它与完整字词完全匹配)。但是,当您 添加f
字符时,您就会获得 修改后的品牌,以删除\
,因为您现在已经搜索两个部分,每个部分匹配该品牌名称的一部分。
我会确保数据保持一致:更新已移除\
的品牌名称以放回&符号。然后当人们使用&
进行搜索时不使用添加了额外的&
,它将完全匹配。这种行为将包含在整个数据中,并且不需要您添加代码来规避FTS的自然操作,这似乎是一种容易出错的方法。