2014-10-03 59 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; 
     } 
}