Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use SqlCommand to CREATE DATABASE with parameterized db name?

To put it short. I've got two simple helpers:

    private SqlCommand CreateCommand(string text)
    {
        SqlCommand cmd = new SqlCommand();
        cmd.Connection = connection;
        cmd.CommandType = CommandType.Text;
        cmd.CommandText = text;
        return cmd;
    }

    void SetParameter(SqlCommand cmd, string p, string dbName)
    {
        cmd.Parameters.Add(p, SqlDbType.NVarChar);
        cmd.Parameters[p].Value = dbName;
    }

This executes OK:

var cmd = CreateCommand("CREATE DATABASE Demo "+
            @"ON (FILENAME = N'c:\demo_data.mdf') "+ 
            @"LOG ON (FILENAME = N'c:\demo_data.mdf.LDF') "+
            "FOR ATTACH " +
            "GO");
cmd.ExecuteNonQuery();

But this doesn't:

string dataBaseAttachText = "CREATE DATABASE @dbname " +
                              "ON (FILENAME = @filename) " +
                              "LOG ON (FILENAME = @filenamelog) " +
                              "FOR ATTACH GO";
var cmd = CreateCommand(dataBaseAttachText);

SetParameter(cmd, "@dbname", "Demo");
SetParameter(cmd, "@filename", @"c:\demo_data.mdf");
SetParameter(cmd, "@filenamelog", @"c:\demo_data.mdf.LDF");

cmd.ExecuteNonQuery();

Why?

like image 383
Mikhail Orlov Avatar asked Aug 19 '10 16:08

Mikhail Orlov


People also ask

How do you add parameters in Ado net?

Should use something like the following: SqlCommand cmd = new SqlCommand("INSERT INTO Product_table Values(@Product_Name, @Product_Price, @Product_Profit, @p)", connect); cmd. Parameters. Add("@Product_Name", SqlDbType.

Which object is used to pass variable to SqlCommand?

Command objects use parameters to pass values to SQL statements or stored procedures, providing type checking and validation. Unlike command text, parameter input is treated as a literal value, not as executable code.


4 Answers

Parameters are supported for DML operations not DDL operations, there are no execution plans for DDL operations. you will need to use dynamic SQL

DDL = Data Definition Language (create, drop, alter....)

DML = Data Manipulation Language (select, update, delete, insert)

like image 68
SQLMenace Avatar answered Oct 05 '22 15:10

SQLMenace


Sadly you can accomplish this by wrapping your DDL operation in a DML operation.

var createDatabaseQuery = "exec ('CREATE DATABASE ' + @databaseName)";

var sqlCommand = new SqlCommand(createDatabaseQuery, sqlConnection);
sqlCommand.Parameters.Add("@databaseName", SqlDbType.Text);
sqlCommand.Parameters["@databaseName"].Value = "HelloWorld";

sqlCommand.ExecuteNonQuery();
like image 40
Rich Hildebrand Avatar answered Oct 05 '22 14:10

Rich Hildebrand


You can only use parameters in places where SQL Server supports them. Unfortunately SQL Server does not support parameterised CREATE DATABASE statements (although I have a feeling the filename parts may support parameters).

You'll need to construct the SQL yourself:

string dataBaseAttachText = "CREATE DATABASE [" + dbName + "] " + 
                              "ON (FILENAME = @filename) " + 
                              "LOG ON (FILENAME = @filenamelog) " + 
                              "FOR ATTACH GO"; 
var cmd = CreateCommand(dataBaseAttachText); 

SetParameter(cmd, "@filename", @"c:\demo_data.mdf"); 
SetParameter(cmd, "@filenamelog", @"c:\demo_data.mdf.LDF"); 

cmd.ExecuteNonQuery(); 

CAUTION: this is susceptable to SQL-injection attacks so caremust be taken; if you don't trust the source of the database name, don't do this!

You'll need to make similar changes to the filename parts if those can't be parameterised either.

like image 33
Daniel Renshaw Avatar answered Oct 05 '22 13:10

Daniel Renshaw


As a bit of a combination of both Daniel's and Rich's answer. By running a DML query to sp_executesql you can have a dynamically built query, also by using QUOTENAME it should escape any attempts at sql injection someone may pass in.

string dataBaseAttachText = @"
DECLARE @SQLString nvarchar(500);
DECLARE @ParmDefinition nvarchar(500);
SET @SQLString =
     N'CREATE DATABASE ' + QUOTENAME(@dbName) + N' 
       ON (FILENAME = @filename) 
       LOG ON (FILENAME = @filenamelog) 
       FOR ATTACH GO'
SET ParmDefinition = N'@filename nvarchar(MAX), @filenamelog nvarchar(MAX)'
EXECUTE sp_executesql @SQLString, @ParmDefinition, @filename = @filename, @filenamelog = @filenamelog";

var cmd = CreateCommand(dataBaseAttachText); 

SetParameter(cmd, "@dbname", "Demo");
SetParameter(cmd, "@filename", @"c:\demo_data.mdf"); 
SetParameter(cmd, "@filenamelog", @"c:\demo_data.ldf"); 

cmd.ExecuteNonQuery(); 

This should execute the following DML sql query with the proper parameters passed.

CREATE DATABASE [Demo]
       ON (FILENAME = @filename) 
       LOG ON (FILENAME = @filenamelog) 
       FOR ATTACH GO
like image 39
Scott Chamberlain Avatar answered Oct 05 '22 15:10

Scott Chamberlain