我得到一些用户在UI上输入的SQL语句:
select * from [table] where [col1] is not null and col2 <> 0
我需要验证所有列名(col1和col2)是否在括号内(如col1)。如果任何列名不在括号中(在本例中为col2),则显示一些弹出消息。
有没有办法在C#中进行这样的SQL验证?
答案 0 :(得分:1)
关于解析SQL,您可以使用Visual Studio附带的TSqlParser library。此解析器接受一个继承自TSqlFragmentVisitor的访问者类,并覆盖ColumnReferenceExpression
的访问方法。
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Microsoft.SqlServer.TransactSql.ScriptDom;
namespace ConsoleApplication8
{
public class QueryParser
{
public IEnumerable<string> Parse(string sqlSelect)
{
TSql100Parser parser = new TSql100Parser(false);
TextReader rd = new StringReader(sqlSelect);
IList<ParseError> errors;
var columns = new List<string>();
var fragments = parser.Parse(rd, out errors);
var columnVisitor = new SQLVisitor();
fragments.Accept(columnVisitor);
columns = new List<string>(columnVisitor.Columns);
return columns;
}
}
internal class SQLVisitor : TSqlFragmentVisitor
{
private List<string> columns = new List<string>();
private string GetNodeTokenText(TSqlFragment fragment)
{
StringBuilder tokenText = new StringBuilder();
for (int counter = fragment.FirstTokenIndex; counter <= fragment.LastTokenIndex; counter++)
{
tokenText.Append(fragment.ScriptTokenStream[counter].Text);
}
return tokenText.ToString();
}
public override void ExplicitVisit(ColumnReferenceExpression node)
{
columns.Add(GetNodeTokenText(node));
}
public IEnumerable<string> Columns {
get { return columns; }
}
}
public class Program
{
private static void Main(string[] args)
{
QueryParser queryParser = new QueryParser();
var columns = queryParser.Parse("SELECT A,[B],C,[D],E FROM T WHERE isnumeric(col3) = 1 Order by Id desc");
foreach (var column in columns)
{
Console.WriteLine(column);
}
}
}
}
但是,我不确定解析用户在UI中输入的SQL是个好主意。即使您在沙盒装环境中运行SQL语句,其中用户只具有读取权限(我希望您这样做),但它不是非常用户友好。作为用户,我希望能够使用复选框选择我想要的列,或者通过拖放它们而不必编写SQL查询。