简体   繁体   English

T-SQL从表中删除*然后插入表

[英]T-SQL Delete * from table then insert into table

Hello I'm trying to do following 您好,我正在尝试追踪

  1. Delete all from table X 从表X中删除所有
  2. insert desired values into table X 将所需的值插入表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. 我认为T-SQL将是实现这一目标的方法,因为当INSERT命令中出现问题时,所有内容都会被删除。

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. 您的问题出在您的foreach循环中。 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. 您还可以使用Where扩展方法,因为它是UI元素,所以可以从数据源中过滤掉所有无效行。

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... 截断表仅在表没有外键约束的情况下才起作用...它可能在那里失败,然后在catch语句中回滚事务...

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(); 您所做的参数完全错误,因为catch的唯一内容是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 下一个问题是,如果表具有任何外键约束,则TRUNCATE TABLE将失败,如果失败,则可以简单地将其替换为

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 至于为什么插入不起作用,您将在for循环的每个实例中放置该命令,还尝试每次都重新添加参数,并将该循环重新格式化为以下形式

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. 但是,您的代码可以做得更好,如果DataGridView是通过绑定由DataTable支持的,则可以改用SqlTableAdapter,比如说您从数据库中加载表,将其显示在网格上,然后再推回更新信息。 With a DataTable it would be as simple as 使用DataTable,它就像

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;
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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