2016-09-22 53 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

相關問題