3

I have many files for procedures, views, functions, etc.

I want to execute these files (creating components) in appropriate database on SQL Server 2005/2008.

Also the point is I want to execute them using C#.

Another point to mention, I want the application to be such that I can execute this files on a remote SQL Server too. Also client machine may not have osql,sqlcmd command tool.

Can someone please guide me on this.

Sunil Agarwal
  • 4,097
  • 5
  • 44
  • 80
  • Can you explain what the files are. Do you want to create a .net dll component to do each of these functions in c# code? – PMC Jan 26 '11 at 18:09
  • The files are normal .sql files. No I dont want to create dll components. I just want to install them once. – Sunil Agarwal Jan 26 '11 at 18:14

5 Answers5

7

This depends on what sort of files they are. If, for example, they only contain actual T-SQL commands (and aren't batch files that you'd run in, say, SSMS, which would contain a batch separator like GO), then you just need to create a connection, a command, then read the contents of the file and use that to populate the CommandText property of the command.

For example:

void ExecuteFile(string connectionString, string fileName)
{
    using(SqlConnection conn = new SqlConnection(connectionString))
    {
        string data = System.IO.File.ReadAllText(fileName);

        conn.Open();

        using(SqlCommand cmd = conn.CreateCommand())
        {
            cmd.CommandText = data;
            cmd.ExecuteNonQuery();
        }
    }
}

If it's a batch file, you'll need to split the file into individual batches and process those individually. The simplest method is just to use string.Split, but bear in mind that it won't respect SQL parsing rules when it splits (for example, if GO appears within a SQL statement, it's going to split the command up into two batches, which will obviously fail).

More generally, you can see what you'd need to do here by modifying the code in this way:

string[] batches = SplitBatches(System.IO.File.ReadAllText(fileName));

conn.Open();

using(SqlCommand cmd = conn.CreateCommand())
{
    foreach(string batch in batches)
    {
        cmd.CommandText = batch;
        cmd.ExecuteNonQuery();
    }
}

The implementation of a function called SplitBatches is up to you.

Adam Robinson
  • 182,639
  • 35
  • 285
  • 343
  • Thanks for the answer. But I still have some doubt. In .sql files I am having the code like this >if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[usp_CheckID]') and > OBJECTPROPERTY(id, N'IsProcedure') = 1) >drop procedure [dbo].[usp_CheckID] >GO //Code to create procedure – Sunil Agarwal Jan 26 '11 at 18:27
  • Hence while executing the file I am getting error Incorrect syntax near 'GO'. 'CREATE/ALTER PROCEDURE' must be the first statement in a query batch. Incorrect syntax near the keyword 'else'. Incorrect syntax near 'GO'. – Sunil Agarwal Jan 26 '11 at 18:33
  • @Sunil: The you have a batch file; see the second part of my answer on how to handle that. The `GO` command is not a SQL command, it's just something that is a standard string used to separate SQL batches in things like SSMS or Visual Studio. You have to split the batches up yourself if you want to process them in this way. – Adam Robinson Jan 26 '11 at 18:34
3

Typically, the simplest way is to split the script on the "GO" statement and execute each item separately. This solution will not work if the script contains a GO statement within a comment.

private readonly Regex _sqlScriptSplitRegEx = new Regex( @"^\s*GO\s*$", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled );
public void ExecuteSqlScript( string scriptText )
{
    if ( string.IsNullOrEmpty( scriptText ) )
        return;

    var scripts = _sqlScriptSplitRegEx.Split( scriptText );
    using ( var conn = new SqlConnection( "connection string" ) )
    {
        using ( var ts = new TransactionScope( TransactionScopeOption.Required, new TimeSpan( 0, 10, 0 ) ) )
        {
            foreach ( var scriptLet in scripts )
            {
                if ( scriptLet.Trim().Length == 0 )
                    continue;

                using ( var cmd = new SqlCommand( scriptLet, conn ) )
                {
                    cmd.CommandTimeout = this.CommandTimeout;
                    cmd.CommandType = CommandType.Text;
                    cmd.ExecuteNonQuery();
                }
            }

            ts.Complete();
        }
    }
}
Thomas
  • 63,911
  • 12
  • 95
  • 141
2

Normally all you have to do is just execute them with SqlCommand.ExecuteNonQuery, one batch at a time. That leaves you the task of splitting the scripts into batches, using the currently set batch delimiter (usually GO). The free library dbutilsqlcmd can be used to handle SQL scripts, as it processes not only the delimiter, but SQLCMD extensions as well (:setvar, :connect etc).

Remus Rusanu
  • 288,378
  • 40
  • 442
  • 569
0

Using standard ADO would "work" -- SQL DDL can be sent using SqlCommand.ExecuteNonQuery, for instance.

...but I'd recommend using a Database Project (with a remote staging deploy or VSDBCMD) or one of the tools such as SQLCMD (perhaps in conjunction with a PowerShell script :-) or SQL Management Studio, etc. They are designed for this sort of stuff.

  • Sorry I dont want to use SQLCMD as I want to execute these files from my machine (not having osql, sqlcmd) to remote machine (sql server installed here) – Sunil Agarwal Jan 26 '11 at 18:17
  • @Sunil Agarwal VSDBCMD (and likely SQLCMD) can be "packaged" for remote-deployment w/o installing. See the [2008 Feature Pack](http://www.microsoft.com/downloads/en/details.aspx?FamilyID=b33d2c78-1059-4ce2-b80d-2343c099bcb4) which may include additional utils (likely require install, but might be able to run them sans-install, haven't try). If there is network access to the target machine (from your current machine or a *staging machine*) then that's just "the easy way" ;-) Hope you find a nice solution. There are also 3rd-party tools. –  Jan 26 '11 at 18:26
  • @Sunil Agarwal One reason to use a Database Project (VSDBCMD deploy is an option) to another database specific project tooling (e.g. 3rd party) is to easily be able to generate/compare/merge changes, etc. (Although, I have yet to find out how to use VSDBCMD successfully for anything but an initial import. VSDBCMD does work really well for an initial import though.) *Additionally, the intermediate result of a VSDBCMD is (one large, but plain) SQL file, which may make deployment easier in and of itself.* I have not played around with additional captures or deployment forms e.g. "Script Changes". –  Jan 26 '11 at 18:29
0

You could read in the commands using a TextReader, then use ExecuteNonQuery with the TextReader results as the command.

MAW74656
  • 3,449
  • 21
  • 71
  • 118