2013-07-15 58 views
3

我試圖分割字符串這是一個SQL語句的WHERE子句與5個輸出陣列,其中下面的數據是每個索引下保持:分裂一個WHERE SQL子句成陣列

0 - The initial clauses (WHERE/AND/OR) plus any open brackets. e.g "AND(((" 
1 - Either the table the first clause comes from or "VALUE" if its a value. e.g. "transactions". 
2 - The field name or value. e.g. "id" 
3 - The joining value. e.g. > 
4 - Either the table the second clause comes from or "VALUE" if its a value. e.g. "transactions". 
5 - The field name or value. e.g. "id" 
6 - Any closing brackets. e.g. ")))" 

對於例如,通過下面的字符串將輸出以下陣列循環:

WHERE transactions.status_code= 'AFA 2' 
AND (transactions.supp_ref = supplier.supp_ref 
AND supplier.supp_addr_ref = address.addr_ref) 
OR transactions.user_code = user.user_code 

output[0] = "WHERE" 
output[1] = "transactions" 
output[2] = "status_code" 
output[3] = "=" 
output[4] = "VALUE' 
output[5] = "AFA 2" 
output[6] = "" 

output[0] = "AND(" 
output[1] = "transactions" 
output[2] = "supp_ref" 
output[3] = "=" 
output[4] = "supplier" 
output[5] = "supp_ref" 
output[6] = "" 

output[0] = "AND" 
output[1] = "supplier" 
output[2] = "supp_addr_ref" 
output[3] = "=" 
output[4] = "address" 
output[5] = "addr_ref" 
output[6] = ")" 

output[0] = "OR" 
output[1] = "transactions" 
output[2] = "user_code" 
output[3] = "=" 
output[4] = "user" 
output[5] = "user_code" 
output[6] = "" 

對於SQL語句的其餘部分我已經成功地使用了String.Split方法類似的方式分割它,但由於其中的差異條款我在這方面遇到了困難。從環顧四周,我想我會更好地使用正則表達式,但無法找出需要的東西。任何幫助或方向將不勝感激。

+2

爲什麼地球上,你會想要做這樣的事情? – LoztInSpace

+2

雖然我無法回答您的問題,但是您需要解析SQL嗎?這不是一項微不足道的任務。你試圖解決什麼潛在的問題,你將如何處理標記化的SQL? – CodeCaster

+0

它有什麼是BETWEEN,IN或一些子查詢? –

回答

0

好的,首先我想正則表達式可能不適合你正在做的事情。話雖這麼說,這是一個正則表達式,它將分析您發佈什麼,並把它變成你正在尋找:

(?<Group>(?<Concat>where|\s*?\)?\s*?and\s*?\(?|\s*?\)?\s*?or\s*?\(?)(?<TableName>[\w\s]+(?=\.))\.?(?<ColName>.+?(?=\=|like|between|\<\>|\>\=|\<\=|in|\>|\<))\s*?(?<Compare>\=|like|between|\<\>|\>\=|\<\=|in|\>|\<)(?<Value>.*?(?=\s*?and\s*?\(*|or\*?\(*)|.*)) 

我敢肯定,這並不能掩蓋一切,取決於正則表達式解析器,這可能表現不同。我使用The Regulator進行我的正則表達式工作。

我會建議編寫一個解析器來做到這一點。看看下面的內容,如果你決定走這條路,這可能會有所幫助。我不完全確定你在那裏使用那個「VALUE」字符串在做什麼,但是如果你正在尋找什麼是一個值,什麼是table.colName,你可以很容易地將它添加到這個。在('a','b')中識別事物會更困難,但我認爲它是可行的。

//A list of chars that we are going to replace with \s"char"\s this list may not be complete. 
    // . is not in here. We will take care of that later. 
    static string[] specChars = new string[] { "<", ">", "<=", ">=", "=", "like", "in", "between", "or", "and", "(", ")", "where" }; 
    static string[] delims = new string[] {"and", "or", "where" }; 
    static string testData = @"WHERE transactions.status_code= 'AFA 2' 
    AND (transactions.supp_ref = supplier.supp_ref 
    AND supplier.supp_addr_ref = address.addr_ref) 
    OR transactions.user_code = user.user_code"; 
    static void Main(string[] args) 
    { 
     Print(Parse(testData)); 
     Console.ReadKey(); 
    } 

    static List<List<string>> Parse(string input) 
    { 
     List<List<string>> ret = new List<List<string>>(); 
     //lets remove all the spaces first becaue we are going to put them back 
     //the way we want to see them. 
     input = input.Replace(" ", "").Replace("\r", "").Replace("\n", "").ToLower(); 
     foreach (string item in specChars) 
     { 
      //this will help clean the string so you can use it 
      input = input.Replace(item, string.Format(" {0} ", item)); 
     } 
     string[] splits = input.Split(' '); 

     List<string> currList = null; 
     foreach (string item in splits.Where(x => x.Length > 0)) 
     { 
      if (delims.Contains(item)) 
      { 
       if (currList != null) 
       { 
        ret.Add(currList); 
        currList = new List<string>(); 
        currList.Add(item); 
       } 
       else 
       { 
        currList = new List<string>(); 
        currList.Add(item); 
       } 
      } 
      else 
      { 
       if (item.Contains(".")) 
       { 
        string[] tmp = item.Split('.'); 
        currList.Add(tmp[0]); 
        currList.Add(tmp[1]); 
       } 
       else 
        currList.Add(item); 
      } 
     } 
     if (currList != null) 
      ret.Add(currList); 
     return ret; 
    } 

    static void Print(List<List<String>> input) 
    { 
     StringBuilder sb = new StringBuilder(); 
     foreach (List<String> item in input) 
     { 
      sb.Append("New Chunk:\n"); 
      foreach (string str in item) 
      { 
       sb.Append(string.Format("\t{0}\n", str)); 
      } 
      sb.Append("\n"); 
     } 

     Console.WriteLine(sb.ToString()); 
    } 
} 
0

如果您正在分析SQL,您可能需要查看ScriptDom命名空間。它可能不僅僅是你想要做的,但它有一些SQL解析器,可以給你關於給定的SQL查詢的詳細信息。

以下是一些資源。

MSDN ScriptDOM reference
An easier introduction