2014-10-03 67 views
1

有點難倒了。我面前的任務是獲取存儲在字符串中的SQL查詢(讓我們假設它現在是一個有效的查詢);將「選擇列表」存儲在字符串數組中,每個數組元素與選擇列表項相關;最後將「from子句」存儲在它自己的字符串變量中。我覺得練習是編寫我自己的SQL查詢解析器,但我不知道SQL Server如何解析查詢。任何方向的資源,可以幫助將非常感激。解析SQL Server查詢而不對數據庫連接執行查詢

我已經能夠使用蠻力的方法,我做下面要解決的問題:

1 - 找到FROM子句通過啓動一個循環找到這個詞的後續實例「從」直到一切隨後的指數位置可以用「SELECT *」選擇列表

private string GetFromClause(string selectstatement,string connectionString) 
{ 
    string teststatement = selectstatement; 
    int startindex = GetFirstFromIndex(teststatement); 
    while (startindex != -1) 
    { 
     teststatement=teststatement.Substring(startindex); 
     if (DoesSelectWork(string.Format("select * {0}", teststatement) 
                , connectionString)) 
      return teststatement; 
     else 
      startindex = GetNextFromIndex(teststatement); 

    } 
    throw new ReportException("Could not find From Clause"); 
} 

2-工作刪除現在發現「FROM子句」從通過查詢;使用.split(',')將剩餘的字符串放在數組中。現在遍歷數組並使用找到的「from子句」測試每個數組元素。如果測試通過,我們有一個有效的選擇列表項目;如果不是我們想這個元素與一個數組元素相結合,並繼續這樣做,直到測試通過(處理鑄造報表等,這將帶來逗號。選擇列表中的語法)

private string[] GetSelectFields(string query, 
           string fromclause, 
           string connectionString) 
{ 
    int index = query.IndexOf(fromclause); 
    string fromless = (index < 0) 
     ? query 
     : query.Remove(index, fromclause.Length); 
    fromless = fromless.Substring(fromless.IndexOf("SELECT") + "SELECT".Length); 
    List<string> finalselect = new List<string>(); 
    string[] selectFields = fromless.Split(','); 
    index = 0;    
    string currentString = string.Empty; 
    while (index<selectFields.Length) 
    { 
     currentString += selectFields[index]; 
     if (DoesSelectWork(string.Format("select {0} {1}" 
       , currentString, fromclause), connectionString)) 
     { 
      finalselect.Add(currentString); 
      currentString = string.Empty; 
     } 
     else { 
      currentString += ","; 
     } 
     index++; 
    } 
    return finalselect.ToArray(); 
} 
+0

聽起來像你正在測試,如果字符串*是*對我有效的查詢? – jbutler483 2014-10-03 16:26:03

+0

這裏使用存儲過程有什麼問題?爲什麼不使用存儲過程並進行整個字符串查詢? – Rex 2014-10-03 16:26:53

+1

http://stackoverflow.com/questions/3276035/code-to-validate-sql-scripts – Jhon 2014-10-03 16:28:04

回答

2

作爲一般的規則是,你不能用一個簡單的搜索方法解析SQL,這些規則太複雜了。你需要一個完整的詞法和語法。但是,自SQL Server 2012以來,您擁有Transact-SQL語言服務選項,這是Visual Studio用來解析無後端服務器的T-SQL的工具。您可以通過 Microsoft.SqlServer.Management.SqlParser.Parser.Parse()從C#利用它。

+0

我認爲['TSqlParser'](http://msdn.microsoft.com/en-us/library/microsoft。 data.schema.scriptdom.sql.tsqlparser(v = vs.100).aspx)和由@JhonAlx鏈接的'ScriptDom'實際上是一個更好的選擇。更好地記錄。 – 2014-10-03 16:40:26

2

如果您想驗證SQL語法而不使用數據庫,那麼TSql100Parser類將適用於這種情況。

聲明,這個職位在這裏Code to validate SQL Scripts

相當簡單的,雖然使用借來的代碼。如果它返回null,那麼在解析它時沒有錯誤。

using Microsoft.Data.Schema.ScriptDom; 
using Microsoft.Data.Schema.ScriptDom.Sql; 

public class SqlParser 
{ 
     public List<string> Parse(string sql) 
     { 
      TSql100Parser parser = new TSql100Parser(false); 
      IScriptFragment fragment; 
      IList<ParseError> errors; 
      fragment = parser.Parse(new StringReader(sql), out errors); 
      if (errors != null && errors.Count > 0) 
      { 
       List<string> errorList = new List<string>(); 
       foreach (var error in errors) 
       { 
        errorList.Add(error.Message); 
       } 
       return errorList; 
      } 
      return null; 
     } 
}