2013-10-09 36 views
2

我在我的asp.net網站中實現了全文搜索,該搜索在搜索一個表時起作用。但是,我希望用戶能夠同時搜索兩個完全不同的表格。我用下面的代碼嘗試這樣的:瓶坯在多個表上的全文搜索

public List<Article> Search(List<string> keywords) 
    { 
     StringBuilder sqlBuilder = new StringBuilder(); 
     sqlBuilder.Append("select [aName],[aDesc] from [Table1] union select [bName],[bDesc] from [Table2] where"); 

     foreach (string item in keywords) 
     { 
      sqlBuilder.AppendFormat("([bName] like '%{0}%' or [bDesc] like '%{0}%') and ", item); 
     } 


     //foreach (string item in keywords) 
     //{ 
      //sqlBuilder.AppendFormat("([aName] like '%{0}%' or [aDesc] like '%{0}%') and ", item); 
     //} 


     string sql = sqlBuilder.ToString(0, sqlBuilder.Length - 4); 
     return QueryList(sql); 

    } 

這個代碼總是顯示所有記錄從我的第一個表,並且只對第二臺搜索。現在這顯然是因爲我沒有在sql語句中的第一個表的'where'。我無法弄清楚如何爲不同'foreach'循環的每個表實現'where'。有什麼建議麼?

回答

2

UNION將加入兩個不同查詢的結果。每個查詢執行完成後,聯合應用,所以你需要兩個WHERE條款:

select [aName],[aDesc] from [Table1] 
where ([aName] like '%{0}%' or [aDesc] like '%{0}%') 

union 

select [bName],[bDesc] from [Table2] 
where ([bName] like '%{0}%' or [bDesc] like '%{0}%') 

在你的代碼最簡單的實現將涉及分別建立這兩個查詢,然後一起加入他們:

StringBuilder sqlBuilder = new StringBuilder(); 
sqlBuilder.Append("select [aName],[aDesc] from [Table1] where "); 
foreach (string item in keywords) 
{ 
    sqlBuilder.AppendFormat(
     "([aName] like '%{0}%' or [aDesc] like '%{0}%') and ", item); 
} 

// That last "AND" requires a boolean statement to follow 
// 1=1 will always return true and thus will not affect 
// the result of your WHERE clause. 
sqlBuilder.Append("1 = 1 "); 

sqlBuilder.Append("UNION select [bName],[bDesc] from [Table2] where "); 
foreach (string item in keywords) 
{ 
    sqlBuilder.AppendFormat(
     "([bName] like '%{0}%' or [bDesc] like '%{0}%') and ", item); 
} 

foreach循環的替代:

sqlBuilder.Append("select [aName],[aDesc] from [Table1] where "); 
sqlBuilder.Append(
    string.Join(
     " and ", 
     keywords.Select(k => string.Format( 
      "([aName] like '%{0}%' or [aDesc] like '%{0}%')", k) 
     .ToArray() 
    ) 
) 

sqlBuilder.Append("UNION select [bName],[bDesc] from [Table2] where "); 
sqlBuilder.Append(
    string.Join(
     " and ", 
     keywords.Select(k => string.Format( 
      "([bName] like '%{0}%' or [bDesc] like '%{0}%')", k) 
     .ToArray() 
    ) 
) 

請注意,雖然,將是一個極端查詢效率低下。如果你有超過幾百行的搜索,我高度建議你考慮替代方法。

此外,您似乎很容易受到SQL Injection attacks。除非您已經手動清理您的輸入,否則您應該考慮protecting yourself

[[A woman is talking on the phone, holding a cup]] Phone: Hi, this is your son's school. We're having some computer trouble. Mom: Oh dear—did he break something? Phone: In a way— Phone: Did you really name your son "Robert'); DROP TABLE Students;--" ? Mom: Oh, yes. Little Bobby Tables, we call him. Phone: Well, we've lost this year's student records. I hope you're happy. Mom: And I hope you've learned to sanitize your database inputs. {{title-text: Her daughter is named Help I'm trapped in a driver's license factory.}}

+0

@BrianBrian - 因爲你的 「無上限」'和'的,也許? – JDB

+0

如何用1 = 1來限制它? –

+0

@BrianBrian - 編輯 – JDB