2016-09-22 50 views
2

我有一个非常特殊的情况。我的ASP.NET页面调用我们的存储过程,对我们的数据库执行全文搜索查询。一些常见的搜索字符串包括一个&符号,因为我们的几个品牌的产品(知名品牌)也有一个&的名字。使用CONTAINSTABLE转义SQL Server全文搜索查询中的&符号

事实证明,在一定的情况下,我没有得到任何结果除非我逃脱符号\&),并在其他一些情况下,我没有得到任何结果只有当我逃离符号

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

这些字符串(&b&c)有可能具有自己的特殊含义吗?而通过转义他们我实际上是传递一个特殊的字符串到T-SQL?

EDIT

附加信息:经过进一步的测试中,我证明了误差在存储过程本身。用&\&调用它会得到不同的结果。

我会尝试发布存储过程的选定部分。我不会发表全部内容,因为大部分内容并不真正相关。

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] 
[...] 

EDIT 2

非常感谢@srutzky指着我在正确的方向!与此同时,我还发现数据不一致,其中名称中的&其中一个品牌被修改为不具有&,而另一个品牌未被修改(底线,我目前的问题是由于:a部分修复是由某人在过去做出的)。

无论如何,回到正轨。现在我明白CONTAINSTABLE函数中的&字符被视为逻辑AND(非按位)。

我仍然需要一个解决方案。 This answer给出了一个不适合我的解决方案(条件与我的不一样)。我怎样才能执行一个CONTAINSTABLE搜索字符串与&符号?最好不必将&符号转换为另一个安全字符?

+0

不确定它是否与您的问题有关,而且是T-SQL中的按位和运算符。 – Kevin

+1

您能向我们展示您正在执行的查询的示例以及表中列的类型吗? – Dalorzo

+1

请向我们展示您的存储过程 – EricZ

回答

2

你所看到的奇怪的行为很可能是由于使用符号(&)字符等同于AND运营商CONTAINSCONTAINSTABLE功能(可以使用SQL Server的全文搜索功能使用)。下面的语句被从文档采取CONTAINS

的连字符(&)可被用来代替与关键字来表示AND运算符。

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


UPDATE

立足现在在问题的“编辑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的自然操作,这似乎是一种容易出错的方法。

+0

非常感谢!我尝试了几个实验,现在我明白了AND运算符的作用,但是我仍然需要一个解决方案:是否有可能以某种方式“逃避”&符号?如果我不想将它转换为安全的字符 – Simone

+0

@Simone请看我的更新.. –

+0

你的回答非常好,真的有帮助!我还有一个问题:为什么'r \&f''还没有返回'r&f'记录, 'r&f''? – Simone

相关问题