Reputation: 3279
I've googled a lot about my question and even looked at many QAs here in SO, but couldn't find what I was looking for, anyway sorry if it is a duplicate question. This is my scenario: I have a string in C#, and it should be used as a SQL Server query. But this string can be anything, from a simple (select A from B) to a complicated SP (which may contain several commands). How can I explicitly DETECT each query in this string? For instance let's say we have following string:
select columnA from tblB
delete tblD where ID='100'
insert into tblF (name) values ('test')
above text is clearly consisted of 3 different queries, each of which should be executed in its own specific way, i.e. the first one (select) needs ExecuteReader, and I should display a table of results, while the others require ExecuteNonQuery. So internally I should run 3 SQL queries, but the problem is how can I differentiate between these 3 queries? I cannot simply split string with '\n' as in SQL, a query can be written in multiple lines. What is the best/correct way of detecting different queries. (SQL Server Management Studio is a perfect example of what I'm looking for) Should I use SQL Parsers? If so, what should I be looking for? I've seen a lot of parsers also, but am really confused as I don't know what should I exactly expect from them.
I did my best to describe the problem! Thanks in advance
Upvotes: 3
Views: 1154
Reputation: 452977
You can add a reference to Microsoft.SqlServer.TransactSql.ScriptDom
then this is quite straight forward (at least for the happy path)
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();
}
}
}
}
}
Returns
Upvotes: 6