2017-10-15 39 views
3

我已经搜索了很多关于我的问题,甚至在这里看到很多QA,但无法找到我正在寻找的东西,无论如何抱歉,如果它是一个重复的问题。 这是我的场景: 我在C#中有一个字符串,它应该用作SQL Server查询。但是这个字符串可以是任何东西,从简单的(从B选择A)到复杂的SP(可能包含多个命令)。我如何显式检测这个字符串中的每个查询? 例如假设我们有以下字符串:在C中检测到来自字符串的SQL查询#

select columnA from tblB 
delete tblD where ID='100' 
insert into tblF (name) values ('test') 

上面的文字显然是由3个不同的查询,每个应在其自己特定的方式执行,即第一个(选择)需要的ExecuteReader和我应该显示一个结果表,而其他的则需要ExecuteNonQuery。所以在内部我应该运行3个SQL查询,但问题是如何区分这3个查询?我不能像在SQL中那样简单地将字符串拆分为'\ n',查询可以用多行书写。检测不同查询的最佳/正确方法是什么? (SQL Server Management Studio是我正在寻找的完美示例) 我应该使用SQL解析器吗?如果是这样,我应该寻找什么?我也看到了很多解析器,但是我真的很困惑,因为我不知道我应该从他们那里期待什么。

我尽力描述问题! 在此先感谢

+5

是非常严重的错你的应用程序,如果你像这样传递随机SQL查询。 –

+0

是的,我知道让用户做任何他想做的事情可能不是一个好主意,但我几乎可以肯定,我总是会得到SQL查询。 –

+0

有一个原因,你没有看到任何谷歌,这是让用户执行任何查询的一个可怕的想法。除了那个“轻微”违反编程101的情况之外,你正试图编写一个sql解析器,这不是一件微不足道的事情。 –

回答

6

您可以添加一个参考Microsoft.SqlServer.TransactSql.ScriptDom那么这是很简单的(至少在幸福路)

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

namespace MyApp 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

      var sql = @" 
SELECT columnA 
FROM tblB 
WHERE ColumnB = 1 

DELETE tblD 
WHERE ID = '100' 

INSERT INTO tblF 
      (NAME) 
VALUES  ('test'), 
      ('foo'), 
      ('bar') 
"; 

      var parser = new TSql100Parser(true); //Or TSql120Parser or whatever 
      IList<ParseError> errors = new List<ParseError>(); 

      TSqlScript script = (TSqlScript)parser.Parse(new StringReader(sql), out errors); 

      //TODO: Don't ignore errors 
      foreach (var batch in script.Batches) 
      { 
       foreach (var st in batch.Statements) 
       { 
        Console.WriteLine(st.GetType().Name); 
        Console.WriteLine(sql.Substring(st.StartOffset, st.FragmentLength)); 
        Console.WriteLine(); 
       } 
      } 
     } 
    } 
} 

返回

enter image description here

+0

这正是我一直在寻找的!你的答案真的值得> 100000谢谢,马丁做得好! –

+1

@Ali_dotNet将批量拆分成语句并单独执行它们并不总是可行。例如,如果其中一个语句是稍后引用的“DECLARE @变量”。管理工作室只会发送整个批次并订阅消息选项卡的信息消息,并循环返回网格的所有结果集。 –

+1

而OUTPUT子句意味着Delete和insert语句可以返回结果集。 –