Keegan Hart
Keegan Hart

Reputation: 23

How to execute Multiple Insert statements in a single query?

I'm making a form where a user answers some questions to make a pricehold. My problem is I can't store the data from the questions into more than one sql table.

I have tried inserting the other table into the sql command (shown below) and I have tried making another sql command that basically says the same thing with a different name but splitting the name and phone number into the first one and the date created and pick up date into the second one but that only runs the first sql command and then stops so data is never stored into the second table

private void AddPhBttn_Click(object sender, RoutedEventArgs e)
    {
        SqlConnection furniture = new SqlConnection("Data Source=LAPTOP-F4QFMPFD\\MSSQLSERVER1;Initial Catalog=Furniture;Integrated Security=True");



        furniture.Open();
        SqlCommand add = new SqlCommand("insert into Customers(Name, Phone) PriceHold(DateCreated, PickUpDate) values ('" + nameTxtBox.Text + "', '" + phoneTxtbox.Text + "', '" + dateTxtBox.Text + "', '" + puDateTxtBox.Text + "')", furniture);

        int i = add.ExecuteNonQuery();
        if (i != 0)
        {
            MessageBox.Show("saved");
        }
        else MessageBox.Show("error");
    }

Upvotes: 0

Views: 2393

Answers (3)

Prashant Pimpale
Prashant Pimpale

Reputation: 10697

As @Caius Jard said, you can't do this with an ad-hoc query.

So what is an option to do so?

Step 1: Create a Stored Procedure in the Database:

CREATE PROCEDURE usp_InsertData
@Name NVARCHAR(200),
@Phone NVARCHAR(100),
@DateCreated Date,
@PickUpDate Date
AS
BEGIN
    SET NOCOUNT ON;
    INSERT INTO Customers(Name, Phone) VALUES (@Name,@Phone)

    INSERT INTO PriceHold(DateCreated, PickUpDate) VALUES (@DateCreated,@PickUpDate) 
END

Step 2: Call above Stored procedure in C# Code:

private void AddPhBttn_Click(object sender, RoutedEventArgs e)
{
     var furniture = new SqlConnection("Data Source=LAPTOP-F4QFMPFD\\MSSQLSERVER1;Initial Catalog=Furniture;Integrated Security=True");

     SqlCommand add = new SqlCommand("usp_InsertData", furniture);
     add.CommandType = System.Data.CommandType.StoredProcedure;

     add.Parameters.AddWithValue("@Name", nameTxtBox.Text);
     add.Parameters.AddWithValue("@Phone", phoneTxtbox.Text);
     add.Parameters.AddWithValue("@DateCreated", dateTxtBox.Text);
     add.Parameters.AddWithValue("@PickUpDate", puDateTxtBox.Text);
     furniture.Open();

     int i = add.ExecuteNonQuery();

     if (i != 0)
     {
          MessageBox.Show("saved");
     }
     else
     {
         MessageBox.Show("error");
     }
     furniture.Dispose();

}

Upvotes: 1

KSK
KSK

Reputation: 695

When working with data in more than one table, if you want to ensure either all insert/update/delete complete successfully or none of them are applied on your data to ensure data integrity, use transactions. I think SqlTransaction is what you're after. Read about it here.

For your specific case, this is one possibility:

private void AddPhBttn_Click(object sender, RoutedEventArgs e)
{
    // Necessary input validation to collect and data from input fields. Good practice to avoid SQL injection.
    AddFurniture(nameTxtBox.Text, phoneTxtbox.Text, dateTxtBox.Text, puDateTxtBox.Text);
}

private void AddFurniture(string name, string phoneNumber, string createdDate, string pickupDate)
{
    string connectionString = "Data Source=LAPTOP-F4QFMPFD\\MSSQLSERVER1;Initial Catalog=Furniture;Integrated Security=True"; // This should ideally come from some configuration.
    using(SqlConnection connection = new SqlConnection(connectionString))
    {
        SqlCommand command = connection.CreateCommand();
        SqlTransaction transaction = connection.BeginTransaction("Add Furniture");
        command.Connection = connection;
        command.Transaction = transaction;

        try
        {
             connection.Open();
            command.CommandText = $"insert into Customers (Name, Phone) values ({name}, {phoneNumber});";
            command.ExecuteNonQuery();
            command.CommandText = $"insert into PriceHold (DateCreated, PickUpDate) values ({createdDate}, {pickupDate});";
            command.ExecuteNonQuery();

            // Try to commit to database.
            // Both the above queries are executed at this point. If any one of them fails, 'transaction' will throw an exception.
            transaction.Commit();
        }
        catch (Exception ex1)
        {
            // Considering the statements executed using the 'transaction' for this 'connection',
            // one of the insert operations have clearly failed.
            // Attempt to roll back the change which was applied.
            MessageBox.Show($"Insert failed. Trying to roll back {ex1.Message}");
            try
            {
                transaction.RollBack();
            }
            catch (Exception ex2)
            {
                // Rollback also failed. Possible data integrity issue. Handle it in your application.
                MessageBox.Show($"Roll back failed. {ex2.Message}");
            }
         }
     }
}

Upvotes: 0

Caius Jard
Caius Jard

Reputation: 74595

You can't do this in SQL

INSERT INTO 
  myfirsttable(column1, column2)
  mysecondtable(column3, column4, column5)
VALUES(value1, value2, value3, value4)

It's flat out a syntax error. Only one table may appear in an insert. The number of values inserted must match the number of columns

If you want to insert into two tables, run two separate inserts from your c# code

Finally, have a long read of http://bobby-tables.com - your code is currently highly insecure and while this may not matter right now because it's just some small test app, it is best to avoid embarking on a learning path that includes coding in this way. As a recruiter I've turned down many job candidates who have written SQL like this and I'd never employ someone who demonstrated this style to me

Upvotes: 0

Related Questions