从用户获取SQL查询并针对SQL Server运行它

时间:2015-08-01 10:49:17

标签: c# sql .net sql-server execute

我想通过C#开发一个非常小的应用程序,它从用户那里得到一些SQL查询并对指定的SQL Server执行它。

SQL Server和数据库必须由用户指定,因此每件事情都可以改变。 我的问题是用户可以输入各种类型的SQL查询,并且每个王者都应该以自己的方式运行。

例如

SELECT * FROM mytable

UPDATE mytable 
SET city = "NY" 
WHERE name = "tom"

无法以相同的方式执行。

我想我需要在我的代码中识别用户查询类型,有没有办法识别它或运行任何可能的查询的更好方法?

4 个答案:

答案 0 :(得分:2)

(这个答案假设您使用System.Data.SqlClient命名空间中的可用类。)

最简单但不是万无一失的方法是检查第一个单词 - 如果它是(不区分大小写)等于SELECT,你可以使用ExecuteReader() - 如果不是,你可以可以使用ExecuteNonQuery()

另一种选择就是ExecuteNonQuery()。如果将SELECT语句作为CommandText传递,则返回-1。检测到此情况后,您可以拨打ExecuteReader()。但是,BEGIN TRANSACTION等其他查询也会返回-1。

答案 1 :(得分:2)

您不需要在代码中创建不同的查询类型。 SqlCommand ExecuteReader方法可用于所有DMLDDL语句。如果语句未返回任何结果,则SqlDataReader Read方法将返回false。您还需要调用SqlDataReader.NextResult方法,直到它返回false以返回多个语句的结果。

var reader = command.ExecuteReader();
do{
    while(reader.Read())
    {
        //process resultset here
    }
}while(reader.NextResult());

答案 2 :(得分:2)

我会使用TSqlPerser.ParseStatementList命名空间中的Microsoft.SqlServer.TransactSql.ScriptDom方法(reference | download #1 - Nuget download #2 - Microsoft® SQL Server® 2014 Transact-SQL ScriptDom):

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SqlServer.TransactSql.ScriptDom;
using System.IO;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            TextReader rdr = new StreamReader(new MemoryStream(
                Encoding.UTF8.GetBytes(
                    @"/* comment */ 
                    WITH CteUpdate 
                    AS
                    (
                        SELECT * FROM Table1 
                        WHERE Col1 = 1
                    )
                    UPDATE CteUpdate SET city = ""NY"" WHERE name = ""tom""")
                ));
            TSql110Parser parser = new TSql110Parser(true);

            IList<ParseError> errors;

            StatementList stmtList = parser.ParseStatementList(rdr, out errors);
            // Process errors
            foreach(TSqlStatement stmt in stmtList.Statements)
            {
                Console.WriteLine("Statement type {0}", stmt.GetType());
                if (stmt is SelectStatement)
                {
                    //Process SELECT statment
                }
                else if (stmt is UpdateStatement)
                {
                    //Process UPDATE statment
                    UpdateStatement stmtUpdate = (UpdateStatement)stmt;
                    NamedTableReference tabRef = (NamedTableReference)stmtUpdate.UpdateSpecification.Target;
                    Console.Write(" > UPDATE statement > target object {0}", tabRef.SchemaObject.BaseIdentifier.Value);
                }
                else //Process other statments
                {
                    throw new NotImplementedException();
                }

            }
        }
    }

}

输出:

  

声明类型   Microsoft.SqlServer.TransactSql.ScriptDom.UpdateStatement&gt; UPDATE   声明&gt;目标对象CteUpdate

答案 3 :(得分:0)

我只是给用户2个执行按钮,一个用于非查询,一个用于阅读 如果您信任用户编写sql语句,则可以信任用户知道要单击的按钮。

不尝试自己分析sql语句的原因很简单: 可以写exec stp_doesThisProcedureSelectsOrUpdates之类的东西,所以你根本无法说出......