2012-08-08 50 views
6

我有一個網站,我需要能夠搜索數據並讓查詢忽略所有引號。SQL Server - 搜索時是否有簡單的方法來忽略引號?

  1. 搜索和檢索具有與啓動字行的結果:
  2. 搜索「你好」「你好」你好和檢索結果行時,有這樣開始的話:「你好」「你好」你好

注:我已經很剝離出來的搜索項通過

我想引號要知道是否有比以下更容易(或更不詳細)的方法:

select Name 
    from tbl_MyTable 
where (Replace(Replace(Replace(Replace(Replace(Replace(Name,'「',''),'‘',''),'''',''),'"',''),'’',''),'」','') like 'dont%' 
    or Replace(Replace(Replace(Replace(Replace(Replace(Name,'「',''),'‘',''),'''',''),'"',''),'’',''),'」','') like '% dont%'); 

現在,我最好的想法是創建一個新的列包含引號剝離的版本(含空格前綴),這樣我可以這樣做:

select Name 
    from tbl_MyTable 
where FixedName like '% dont%'; 

但我真的想知道這是否可以在不產生新的列來完成,並將它是有效的。

+0

我是從C#應用程序查詢的,所以有一點可以在這方面完成的工作,但不會以犧牲性能爲代價。我的代碼實際上是查詢多個表和列(我只是簡化了這裏的情況),所以最好我想要一個數據範圍的答案。 – 2012-08-08 18:18:23

回答

1

使用全文索引而不是等。

創建全文索引:

http://msdn.microsoft.com/en-us/library/ms187317.aspx

CREATE UNIQUE INDEX ix1 ON tbl_MyTable(YourKey); //unique index required 
CREATE FULLTEXT CATALOG ft AS DEFAULT; // ft is your freetext catalog name 
CREATE FULLTEXT INDEX ON tbl_MyTable(Name) 
    KEY INDEX ix1 
    WITH STOPLIST = SYSTEM; // this is your index and allows you to run the command below 

然後用它來運行查詢:

SELECT Name 
FROM tbl_MyTable 
WHERE FREETEXT(Name, 'dont'); 

這對於這種事情的最快方法。如果你使用第三方免費文本引擎,你可以獲得更快的速度,但可能沒有必要這麼做。

+0

所以解決方案是: 1)創建刪除引號的FixedName列。 2)在FixedName列上創建全文索引。 3)... 4)利潤? – 2012-09-26 14:13:13

+0

不,你不需要刪除引號。只需在名稱列上創建全文索引即可。我已經更新了我的答案以反映這一點。 – 2012-09-27 13:54:31

0

我建議創建用戶定義函數來鞏固這一邏輯:

CREATE FUNCTION [dbo].[udf_StripQuotes] 
(
    @String VARCHAR(MAX) 
) 
RETURNS VARCHAR(MAX) 
AS 
BEGIN 
    RETURN Replace(
     Replace(
      Replace(
       Replace(
        Replace(
         Replace(@String,'「',''), 
        '‘',''), 
       '''',''), 
      '"',''), 
     '’',''), 
    '」','') 
END 
GO 

然後看起來像:

select Name 
from tbl_MyTable 
where dbo.udf_StripQuotes(name) like '% dont%'; 

至於效率,領先並在like聲明尾隨%將阻止您使用任何索引,這將導致全表掃描......這可能是此查詢的最大性能。但是,就像Aaron所闡明的那樣,由於調用UDF的開銷,這個實現會比原來慢。

如果您可以避開前導通配符,那麼computed column with an index可能會提高性能。

否則,我認爲你唯一的其他選擇是實施Full-Text Search

+0

這肯定比封裝這個更容易,並且在查詢中引用了這個函數,但是要清楚的是,這會比原來慢,但可能更慢。 – 2012-08-08 18:28:42

+0

@AaronBertrand嗯......我認爲最大的性能影響將來自全表掃描...你認爲將'replace'語句包裝成udf會增加明顯的開銷嗎? – 2012-08-08 18:37:47

+0

那麼在調用函數時會有開銷,並且您將在掃描期間調用函數2 x行計數(因爲存在或條件)。我將在一個我將刪除的答案中解決這個問題。 – 2012-08-08 18:39:53

0

這不是問題的答案,但作爲評論很難實現。

如果您打算使用UDF來簡化查詢本身,請自己幫忙,並將函數調用限制爲您擁有的行數,而不是雙倍。相反的:

where dbo.udf_StripQuotes(name) like 'dont%' 
    or dbo.udf_StripQuotes(name) like '% dont%'); 

這樣做:

where ' ' + dbo.udf_StripQuotes(name) like '% dont%'; 

至於潛在的問題,我與邁克爾同意的索引計算列可能是最好的,但如果名稱,這將是不可能的列超過900個字節(並且由於通配符,這不會奇蹟般地將掃描轉換爲搜索,它只是不需要調用函數或執行查詢中的所有替換調用)。

+0

該列上的全文搜索可以成爲解決方案嗎? – 2012-09-07 17:54:36

0

高效的空間或時間?

您的第一個解決方案是節省空間的,但由於在每次執行查詢時將多個字符串函數應用於表中的每一行,可能會導致效率低下。

生成列的解決方案空間效率低,但由於應用字符串操作一次(當您添加列,然後插入/更新時),可能會節省時間。

從用戶的角度來看,最好的解決方案可能是在生成的列上執行搜索。

0

請嘗試以下操作,將所有名稱返回而不加任何引號或雙引號。這將防止LIKE語句的必要性,避免另一列的必要性,並加快您的查詢:

SELECT Replace(
    Replace(
     Replace(
      Replace(
       Replace(
        Replace(Name, '「', ''), 
       '‘', ''), 
      '''',''), 
     '"', ''), 
    '’',''), 
'」', '') AS Name 
FROM tbl_MyTable