我想通过C#开发一个非常小的应用程序,它从用户那里得到一些SQL查询并对指定的SQL Server执行它。
SQL Server和数据库必须由用户指定,因此每件事情都可以改变。 我的问题是用户可以输入各种类型的SQL查询,并且每个王者都应该以自己的方式运行。
例如
SELECT * FROM mytable
和
UPDATE mytable
SET city = "NY"
WHERE name = "tom"
无法以相同的方式执行。
我想我需要在我的代码中识别用户查询类型,有没有办法识别它或运行任何可能的查询的更好方法?
答案 0 :(得分:2)
(这个答案假设您使用System.Data.SqlClient
命名空间中的可用类。)
最简单但不是万无一失的方法是检查第一个单词 - 如果它是(不区分大小写)等于SELECT
,你可以使用ExecuteReader()
- 如果不是,你可以可以使用ExecuteNonQuery()
。
另一种选择就是ExecuteNonQuery()
。如果将SELECT语句作为CommandText
传递,则返回-1。检测到此情况后,您可以拨打ExecuteReader()
。但是,BEGIN TRANSACTION
等其他查询也会返回-1。
答案 1 :(得分:2)
您不需要在代码中创建不同的查询类型。 SqlCommand ExecuteReader方法可用于所有DML
和DDL
语句。如果语句未返回任何结果,则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
之类的东西,所以你根本无法说出......