I have a very simple C# command shell app that executes a sql script generated by SQL Server for scripting schema and data. It\'s blowing up on the \"GO\" statements. Error
As mentioned in another answer, GO
is not supported.
You can use String.Split()
on your script using your GO
statements as delimiters, and run each segment as a command, separately.
string[] commands = sql.Split(
new string[]{"GO\r\n", "GO ", "GO\t"}, StringSplitOptions.RemoveEmptyEntries );
foreach (string c in commands)
{
command = new SqlCommand(c, masterConnection);
command.ExecuteNonQuery();
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
finally
{
masterConnection.Close();
}
}
Found here. http://blogs.msdn.com/b/onoj/archive/2008/02/26/incorrect-syntax-near-go-sqlcommand-executenonquery.aspx
There is very nice SqlServerBatchParser class inside FluentMigrator library
Supports GO
GO 3
statements.
You need to install FluentMigrator.Runner.SqlServer nuget package
Example generously copied(slightly modified) from FluentMigrator source code:
using FluentMigrator.Runner.BatchParser;
using FluentMigrator.Runner.BatchParser.SpecialTokenSearchers;
using FluentMigrator.Runner.BatchParser.Sources;
void Main()
{
var connString = "Server=.;Database=mydb;Trusted_Connection=True;";
var sql = @"select 1;
GO
SELECT 2;
GO 5";
ExecuteBatchNonQuery(connString, sql);
}
public static void ExecuteBatchNonQuery(string ConnectionString, string sql)
{
var sqlBatch = string.Empty;
var conn = new SqlConnection(ConnectionString);
conn.Open();
try
{
var parser = new SqlServerBatchParser();
parser.SqlText += (sender, args) => { sqlBatch = args.SqlText.Trim(); };
parser.SpecialToken += (sender, args) =>
{
if (string.IsNullOrEmpty(sqlBatch))
return;
if (args.Opaque is GoSearcher.GoSearcherParameters goParams)
{
using (var command = conn.CreateCommand())
{
command.CommandText = sqlBatch;
for (var i = 0; i != goParams.Count; ++i)
{
command.ExecuteNonQuery();
}
}
}
sqlBatch = null;
};
using (var source = new TextReaderSource(new StringReader(sql), true))
{
parser.Process(source, stripComments: true);
}
if (!string.IsNullOrEmpty(sqlBatch))
{
using (var command = conn.CreateCommand())
{
command.CommandText = sqlBatch;
command.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
using (var message = new StringWriter())
{
message.WriteLine("An error occured executing the following sql:");
message.WriteLine(string.IsNullOrEmpty(sqlBatch) ? sql : sqlBatch);
message.WriteLine("The error was {0}", ex.Message);
throw new Exception(message.ToString(), ex);
}
}
finally
{
conn?.Dispose();
}
}
Credits: https://github.com/fluentmigrator/fluentmigrator/blob/v3.2.1/src/FluentMigrator.Runner.SqlServer/Processors/SqlServer/SqlServerProcessor.cs
GO
is not part of SQL, it is something SQL Server Management Studio does for you to split the script up.
What you need to do is read the query in to a string then split on GO
on a line by itself (you may want to use Regex for this)
//Its better to dispose the SqlCommand, I also switched constructors so I could re-use the SqlCommand.
using(SqlCommand command = new SqlCommand())
{
command.Connection = connection;
var scripts = Regex.Split(script, @"^\w+GO$", RegexOptions.Multiline);
foreach(var splitScript in scripts)
{
command.CommandText = splitScript;
command.ExecuteNonQuery();
}
}
Look at Matt Johnson's answer for a less naive implementation of the GO
splitting.
If you want to be able to use GO
you will need to reference to the following dlls
Microsoft.SqlServer.ConnectionInfo.dll
Microsoft.SqlServer.Management.Sdk.Sfc.dll
Microsoft.SqlServer.Smo.dll Microsoft.SqlServer.SqlEnum.dll
Then execute like so
using (SqlConnection conn = new SqlConnection(connection))
{
Server db = new Server(new ServerConnection(conn));
string script = File.ReadAllText(scriptPath);
db.ConnectionContext.ExecuteNonQuery(script);
}