简体   繁体   中英

T-SQL Delete * from table then insert into table

Hello I'm trying to do following

  1. Delete all from table X
  2. insert desired values into table X

I thought then T-SQL would be way to achieve that because when something messes up in the INSERT command then everything will be deleted.

But this code does nothing it doesn't insert or delete the data. May someone help me to fix this issue?

spojeni.Open();
SqlTransaction sqlTrans = spojeni.BeginTransaction();
try
{
    string delCmdTxt = "TRUNCATE TABLE PLODINY";
    SqlCommand cmdDel = spojeni.CreateCommand();
    cmdDel.CommandText = delCmdTxt;
    cmdDel.Transaction = sqlTrans;
    cmdDel.ExecuteNonQuery();

    string insert_sql = 
        "INSERT INTO PLODINY(PLODINA,CENAZAQ,MJ)VALUES(@PLODINA,@CENAZAQ,@MJ)";
    SqlCommand sqlcom = spojeni.CreateCommand();
    sqlcom.CommandText = insert_sql;
    sqlcom.Transaction = sqlTrans;

    foreach (DataGridViewRow row in dataGridView1.Rows)
    {
        sqlcom.Parameters.AddWithValue("@PLODINA", row.Cells["PLODINA"].Value);
        sqlcom.Parameters.AddWithValue("@CENAZAQ", row.Cells["CENAZAQ"].Value);
        sqlcom.Parameters.AddWithValue("@MJ", row.Cells["MJ"].Value);

        sqlcom.ExecuteNonQuery();
        sqlcom.Dispose();
    }
    sqlTrans.Commit();
}
catch (System.Data.SqlClient.SqlException)
{
    sqlTrans.Rollback();
}
finally
{
    spojeni.Close();
    spojeni.Dispose();
}
this.Close();

Your problem is in your foreach loop. You need to define your parameters before hand, and do not dispose the command object until you're all done with it. You can also use the Where extension method to filter out any invalid rows from your data source since its a UI element.

string insert_sql = "INSERT INTO PLODINY(PLODINA,CENAZAQ,MJ)VALUES(@PLODINA,@CENAZAQ,@MJ)";
SqlCommand sqlcom = spojeni.CreateCommand();
sqlcom.CommandText = insert_sql;
sqlcom.Transaction = sqlTrans;
sqlcom.Parameters.Add("@PLODINA");
sqlcom.Parameters.Add("@CENAZAQ");
sqlcom.Parameters.Add("@MJ");

// some validation - add what you need.
var validRows = dataGridView1.Rows.Cast<DataGridViewRow>()
  .Where(row => row.Cells["PLODINA"].Value != null);

foreach (DataGridViewRow row in validRows)
{
    sqlcom.Parameters[0].Value = row.Cells["PLODINA"].Value;
    sqlcom.Parameters[1].Value = row.Cells["CENAZAQ"].Value;
    sqlcom.Parameters[2].Value = row.Cells["MJ"].Value;
    sqlcom.ExecuteNonQuery();
}

sqlTrans.Commit();
sqlcom.Dispose();

Truncate Table only works if the table has not foreign key constraints... it's probably failing there and then rolling back the transaction in the catch statement...

Instead of Truncate try Delete From table and see if that fixes it...

You are doing your parameters totally wrong, because the only thing in your catch is the sqlTrans.Rollback(); you never see the errors you are getting, the first thing I would change is make that catch

catch (System.Data.SqlClient.SqlException)
{
    sqlTrans.Rollback();
    throw;
}

so you can now see the errors happen.

The next issue is if the table has any foreign key constraints your TRUNCATE TABLE will fail, if it is failing you can simply replace it with

string delCmdTxt = "delete from PLODINY";
SqlCommand cmdDel = spojeni.CreateCommand();
cmdDel.CommandText = delCmdTxt;
cmdDel.Transaction = sqlTrans;
cmdDel.ExecuteNonQuery();

As to why your inserts are not working, you are disposing the command every instance of the for loop, you are also trying to re-add the parameters every time, reformat that loop to the following

string insert_sql = "INSERT INTO PLODINY(PLODINA,CENAZAQ,MJ)VALUES(@PLODINA,@CENAZAQ,@MJ)";
using(SqlCommand sqlcom = spojeni.CreateCommand())
{
    sqlcom.CommandText = insert_sql;
    sqlcom.Transaction = sqlTrans;

    sqlcom.Parameters.Add("@PLODINA", SqlDbType.NVarChar); //Replace with whatever the correct datatypes are
    sqlcom.Parameters.Add("@CENAZAQ", SqlDbType.NVarChar);
    sqlcom.Parameters.Add("@MJ", SqlDbType.NVarChar);

    foreach (DataGridViewRow row in dataGridView1.Rows)
    {
        sqlcom.Parameters["@PLODINA"] = row.Cells["PLODINA"].Value;
        sqlcom.Parameters["@CENAZAQ"] = row.Cells["CENAZAQ"].Value;
        sqlcom.Parameters["@MJ"] = row.Cells["MJ"].Value;

        sqlcom.ExecuteNonQuery();    
    }
}
sqlTrans.Commit();

However your code can be made even better, if your DataGridView was backed by a DataTable via binding you could use a SqlTableAdapter instead, Lets say you load the table from the database, display it on the grid, and then you want to push back the updated information. With a DataTable it would be as simple as

private string _getDataQuery = "select PLODINA, CENAZAQ, MJ from PLODINY";

public void GetData(DataTable data)
{
    //You do not need to call open here as SqlDataAdapter does it for you internally.
    using(var spojeni = new SqlConnection(GetConnectionString())
    using(var adapter = new SqlDataAdapter(_getDataQuery, spojeni)
    {
        data.Clear();
        adapter.Fill(data);
    }
}

public void UpdateData(DataTable data)
{
    using(var spojeni = new SqlConnection(GetConnectionString())
    using(var adapter = new SqlDataAdapter(_getDataQuery, spojeni)
    using(var commandBuilder = new SqlCommandBuilder(adapter)
    {
        //This may or may not be nessesary for spojeni.BeginTransaction()
        spojeni.Open();

        using(var sqlTrans = spojeni.BeginTransaction())
        {
            adapter.SelectCommand.Transaction = sqlTrans;

            adapter.UpdateCommand = commandBuilder.GetUpdateCommand();
            adapter.UpdateCommand.Transaction = sqlTrans;

            adapter.DeleteCommand = commandBuilder.GetDeleteCommand();
            adapter.DeleteCommand.Transaction = sqlTrans;

            adapter.InsertCommand = commandBuilder.GetInsertCommand()
            adapter.InsertCommand.Transaction = sqlTrans;

            try
            {
                adapter.Update(data);
                sqlTrans.Commit();
            }
            catch
            {
                sqlTrans.Rollback();
                throw;
            }
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM