我有一个例程,用其他数据库数据更新本地数据库。
我只执行 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();
答案 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评论的那样,我创建了临时表来接收来自外部数据库的数据,然后将数据传输到权威表,以便用户受影响的可能性非常低。