仅当SELECT返回

时间:2017-04-24 22:34:10

标签: c# sql ms-access oledb

我有一个例程,用其他数据库数据更新本地数据库。

我只执行 DELETE ,然后执行 INSERT INTO tblX(SELECT * FROM tblY(tblY是一个链接表)),如下所示。

问题在于,在某些情况下 SELECT 需要很长时间才能 DELETE ,我想减少用户提出请求的可能性处理时到这个表。

我想知道在返回 SELECT 之后是否有某种机制来执行 DELETE

conn = new OleDbConnection(Conexao.getConexaoPainelGerencialLocal());

conn.Open();

OleDbCommand cmd = new OleDbCommand(" DELETE * FROM tblClienteContato; ", conn);

cmd.ExecuteNonQuery();

cmd = new OleDbCommand(" INSERT INTO tblClienteContato " +
                       " SELECT * FROM tblClienteContatoVinculada;", conn);

cmd.ExecuteNonQuery();

4 个答案:

答案 0 :(得分:2)

听起来你需要做的就是在事务中包装这两个命令。

关于交易的一个很酷的事情是 ALL WORKS ALL FAILS ,这意味着如果发生某些事情停止select语句,数据库将无法完成删除声明。

这看起来像是一个非常好的例子: https://msdn.microsoft.com/en-us/library/93ehy0z8(v=vs.110).aspx

请注意,它们有一个命令对象,并替换CommandText,而不是每次都创建一个新对象。这可能很重要。

尝试这样的事情:

conn = new OleDbConnection(Conexao.getConexaoPainelGerencialLocal());
OleDbCommand cmd = new OleDbCommand();
OleDbTransaction transaction = null;

try {

    conn.Open();
    transaction = conn.BeginTransaction(IsolationLevel.ReadCommitted);

    cmd.Connection = conn;
    cmd.Transaction = transaction;



    cmd.CommandText = " DELETE * FROM tblClienteContato; ";
    cmd.ExecuteNonQuery();

    cmd.CommandText = " INSERT INTO tblClienteContato " +
                       " SELECT * FROM tblClienteContatoVinculada;";

    cmd.ExecuteNonQuery();

    // The data isn't _finally_ completed until this happens
    transaction.Commit();


}
catch (Exception ex)
{
    // Something has gone wrong.
    // do whatever error messaging you do
    Console.WriteLine(ex.Message);
    try
    {
        // Attempt to roll back the transaction.
        // this means your records won't be deleted
        transaction.Rollback();
    }
    catch
    {
        // Do nothing here; transaction is not active.
    }
}

答案 1 :(得分:0)

您应该查看BeginTransaction,Commit和rollback,这是一个例子:

    _con.Open();
    _con_trans = _con.BeginTransaction();
    using(SqlCommand cmd = _con.CreateCommand())
    {
        cmd.CommandText = "delete from XXXXX";
        cmd.CommandType = CommandType.Text;
        cmd.Transaction = _con_trans;
        cmd.ExecuteNonquery();
    }

    using(SqlCommand cmd = _con.CreateCommand())
    {
        cmd.CommandText = "insert into XXXX";
        cmd.CommandType = CommandType.Text;
        cmd.Transaction = _con_trans;
        cmd.ExecuteNonquery();
    }
    _con_trans.Commit();
    _con_trans = null;
    _con.Close();

这样,所有内容都包含在一个事务中,因此当删除开始时,表将被锁定以进行读写。

答案 2 :(得分:0)

在不知道表格架构的情况下,很难确定删除过程花费较长时间的原因。

在事务中包装命令的另一种方法是使用Person p; Person *ptoPerson = &p; cout << ptoPerson->printMsg("Hi") << endl; delete ptoPerson; 命令简单地删除表本身而不是其中的数据。然后,您可以使用DROP TABLE语句重新创建表来重新创建。这方面的一个潜在优势是模式将完全匹配,并且不需要进行任何固有的转换(例如,十进制到int)。

SELECT...INTO...FROM

以下内容不适用于此(MS Access),但可能适用于其他SQL变体 另一个选择是使用 using (conn = new OleDbConnection(Conexao.getConexaoPainelGerencialLocal())) { conn.Open(); using (OleDbCommand cmd = new OleDbCommand()) { cmd.CommandText = "DROP TABLE tblClienteContato; "; cmd.ExecuteNonQuery(); cmd.CommandText = "SELECT * INTO tblClienteContato FROM tblClienteContatoVinculada;"; cmd.ExecuteNonQuery(); } } 命令,它将一举删除表中的所有内容。没有记录单个行,并且不需要在每个要删除的行上重新计算索引(如果存在)。这种方法的缺点是这在事务中不起作用。如果存在Identity列,则该值也将重置。还有其他潜在的缺点,但不知道表的设计,我无法识别它们。

TRUNCATE

答案 3 :(得分:0)

正如Greg评论的那样,我创建了临时表来接收来自外部数据库的数据,然后将数据传输到权威表,以便用户受影响的可能性非常低。