解析SQL Server查询而不对数据库连接执行查询
有点难倒了。我面前的任务是获取存储在字符串中的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();
}
作为一般的规则是,你不能用一个简单的搜索方法解析SQL,这些规则太复杂了。你需要一个完整的词法和语法。但是,自SQL Server 2012以来,您拥有Transact-SQL语言服务选项,这是Visual Studio用来解析无后端服务器的T-SQL的工具。您可以通过 Microsoft.SqlServer.Management.SqlParser.Parser.Parse()
从C#利用它。
我认为['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
如果您想验证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;
}
}
听起来像你正在测试,如果字符串*是*对我有效的查询? – jbutler483 2014-10-03 16:26:03
这里使用存储过程有什么问题?为什么不使用存储过程并进行整个字符串查询? – Rex 2014-10-03 16:26:53
http://stackoverflow.com/questions/3276035/code-to-validate-sql-scripts – Jhon 2014-10-03 16:28:04