Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Dynamic SQL INSERT ... SELECT

Tags:

c#

sql

mysql

I am using the INSERT ... SELECT syntax to select existing rows from a table and insert then into another table. In addition to the existing data from each row I also need to add a BillingID and TimeStamp. Because these fields are in the SELECT part of the SQL statement I cannot parametrize them. I solved the TimeStamp issue using the SQL function NOW(), however I am still left with BillingID which I have added to the query via sting concatenation as follows:

static void UpdateMonthlyData(int BillingID, DateTime HistoryDate, int CompanyID)
{   
        String conString = ConfigurationManager.ConnectionStrings["xxx"].ConnectionString;
        MySqlConnection connection = new MySqlConnection(conString);

        String command = "INSERT INTO MonthlyData SELECT " + BillingID + ", d.*, NOW() "  
                       + "FROM CurrentData d WHERE d.CompanyID = @CompanyID AND d.HistoryDate = @HistoryDate";

        MySqlCommand cmd = new MySqlCommand(command, connection);
        cmd.Parameters.Add(new MySqlParameter("@CompanyID", CompanyID));
        cmd.Parameters.Add(new MySqlParameter("@HistoryDate", HistoryDate));

        cmd.CommandType = CommandType.Text;

        cmd.Connection.Open();
        cmd.ExecuteNonQuery();
        cmd.Connection.Close();                          
}

I am not concerned with SQL Injection as this is a console app that is run on an automated schedule and has no user interaction whatsoever. (BillingID is auto-generated). Despite that, I don't like using concatenated strings as they are not very readable. Is there a more elegant way of doing this?

Edit:

To sum things up, I thought that since since you cant do this:

SELECT @field FROM @table

I presumed that parameters are not allowed in the SELECT part of a SQL statement. However since I am specifying a value in the select statement rather than selecting a column, as @cdhowie pointed out I can use a parameter there. In essence my query translated is something like this:

SELECT 25 FROM table_name, not  SELECT field FROM table_name

So now thanks to @cdhowie I understand that a parameter can be anywhere a literal value can be

like image 495
Louise Eggleton Avatar asked Mar 25 '23 05:03

Louise Eggleton


2 Answers

A query parameter is valid anywhere that a literal value would be, assuming that the query parameter is of the correct type (e.g. ... LIMIT @Foo should work as long as you bind an integer -- or something the SQL server can successfully convert to an integer -- to the Foo parameter). This assumes no particular quirks in the SQL dialect you are using, of course.

In other words, there is no reason that you shouldn't be able to pass BillingID using a query parameter.

like image 61
cdhowie Avatar answered Mar 27 '23 16:03

cdhowie


You could use String.Format for any safe fields that cannot be added via parameterization:

String command = String.Format("INSERT INTO MonthlyData SELECT {0}, d.*, NOW() FROM CurrentData d WHERE d.CompanyID = @CompanyID AND d.HistoryDate = @HistoryDate", BillingID);
like image 39
w.brian Avatar answered Mar 27 '23 14:03

w.brian