【问题标题】:How to remove previous sql insert if one after fails?如果一次失败,如何删除以前的 sql 插入?
【发布时间】:2015-03-09 15:58:40
【问题描述】:

当我在一个表 (work_log) 中插入一条新记录时,我会使用 work_log 中最后插入的记录更新另一个表 (employers) 中的记录。
但是如果更新employers-table 不成功,在成功将新记录插入work_log 后,我需要将新添加的记录删除到work_log,因为该条目将不再有效。

到目前为止,这是我的脚本:

/**
 *  This first part has no direct affect on the question, but serves as additional information to understand the script better..
 *  - - -
 *  First, a new work session is inserted (this session has nothing to do with browser session)
 *  If this fails, the script does not continue, and the user is redirected back to the form with an error-message.  
 *  otherwise, the script continues, and try to activate the session by adding a new work_log entry.
 */
$ins_session = $con['site']->prepare('INSERT INTO work_sessions (fields) VALUES (?)');
$ins_session->execute(array(values));
if($ins_session){
    KD::notice('success','New work session is created.');
    $session_id = $con['site']->lastInsertId();
} else {
    KD::notice('error','Work session was not created.');
    KD::redirect();  //  stops the script, and redirects
}

/**
 *  This part affects my question
 *  - - -
 *  Add a new entry to the work log in order to automatically start the work session.
 *  If this entry is successfully inserted, then add an indicator to the corresponding employer, in the employers table, to indicate that this employer has an active session (and which one it is).
 */ 
$ins_work_log = $con['site']->prepare('INSERT INTO work_log (fields) VALUES (?)');
$ins_work_log->execute(array(values));
if($ins_work_log){
    $upd_employer = $con['site']->prepare('UPDATE employers SET fk_work_sessions_id = ? WHERE id = ?');
    $upd_employer->execute(array($session_id,$_POST['employer_id']));
    if($upd_employer){
        KD::notice('success','New session was created and started.');
        KD::redirect();
    } else {
        //  need to remove the entry from work_log.
        KD::notice('Work session was created, but not started. Please start the session manually.');
    }
}

据我了解,我必须删除work_log-table 中最后插入的记录?
有没有其他方法可以做到这一点?比如,以另一个顺序,或者如果这个(更新查询)失败,自动从work_log 中删除条目?

work_log-table 是 innoDB,行格式是 compact,如果知道这一点很重要...

更新
我是这样设置的:
它似乎有效,但我有点不确定我是否正确使用了 if/else 语句。

$con['site']->beginTransaction();
$ins_work_log = $con['site']->prepare('INSERT INTO work_log (fields) VALUES (?)');
$ins_work_log->execute(array(values));
if($ins_work_log){
#   update employer
    $upd_employer = $con['site']->prepare('UPDATE employers SET fk_work_sessions_id = ? WHERE id = ?');
    $upd_employer->execute(array($session_id,$_POST['employer_id']));
    if($upd_employer){
        $con['site']->commit();
        KD::notice('success','New session was created and started.');
    } else {
        $con['site']->rollBack();
        KD::notice('error','Work session was created, but not started. Please start the session manually.');
    }
//
} else {
    $con['site']->rollBack();
    KD::notice('error','');
}
KD::redirect();

if($ins_work_log)if($upd_employer) 在查询尚未提交时会有什么影响吗?

【问题讨论】:

  • 当您使用 INNODB 和合理的连接器(即 mysqli 或 pdo)时,您应该查看 TRANSACTIONS。如果您在第一次插入之前启动事务并且第二次失败则执行 ROLLBACK,如果第二次插入有效则执行 COMMIT。 ROLLBACK 将删除作为事务的一部分所做的任何更改,而您不必担心它们可能是什么
  • 我用一些新代码更新了我的问题。它似乎有效,但我做得对吗?
  • 不,我不认为if($upd_employer) 会做任何事情——您需要查看execute() 的实际返回值。 if($ins_work_log) 也一样。相反,您将它与上面的行结合起来:if ($ins_work_log->execute(array(values))){ 或者将返回值保存在另一个变量中,并对该变量执行条件。

标签: php rollback


【解决方案1】:

这是使用START TRANSACTIONCOMMITROLLBACK的经典案例。

http://dev.mysql.com/doc/refman/5.0/en/commit.html

只要确保您使用的是支持它的数据库引擎即可。

伪代码:

query("START TRANSACTION;");
query("INSERT INTO table1 ...");
if (query("INSERT INTO table2 ..."))
    query("COMMIT;");
else
    query("ROLLBACK;");

【讨论】:

  • 因为我使用的是 PDO,mysql 和表是 innoDB,我想这应该可以工作。但是我已经用一些新代码更新了我的问题。它似乎有效,但我做得对吗?
猜你喜欢
  • 1970-01-01
  • 2013-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
相关资源
最近更新 更多