如果一个更新查询失败,回滚多个更新查询


Rollback multiple update query if one fails

所以我所做的是我有多个UPDATE查询,它改变了tbl_groups表中的组名,然后更新属于该组的tbl_users中的所有用户,但如果用户更新查询失败,它更新组,但我想一起更新或没有,我使用PHP和MySQL。

听起来你所需要做的就是使用事务。

你必须使用InnoDB表来使用事务(实际上,其他一些DB引擎也有事务,但InnoDB在MySQL中最常见)

在第一次更新之前发出"BEGIN TRANSACTION"查询。

如果任何查询失败,发出"ROLLBACK"查询来撤消所有操作。

这真的很简单。

如果您决定要进行部分回滚(回滚到事务开始后的某个点),那么您可以使用"rollback to SAVEPOINT savepoint_name"。您必须首先发出"SAVEPOINT savepoint_name"查询。

。,在PHP中

mysql_query("BEGIN TRANSACTION");
$result1 = mysql_query("UPDATE `tbl_groups` SET `user_id` = 5 WHERE `group_id` = 3");
if($result1 === false) {
mysql_query("ROLLBACK");
}
mysql_query("SAVEPOINT savepoint1");
$result2 = mysql_query("UPDATE `tbl_users` SET `group_id` = 3 WHERE `user_id` = 5");
if($result === false) {
ROLLBACK TO SAVEPOINT savepoint1;
}
// COMMIT saves the changes to the db, making them visible to other sessions
// if the ROLLBACK TO SAVEPOINT statement executed, then only changes up to that SAVEPOINT will be saved
// if no ROLLBACK statements were executed, then all changes will be saved (assuming no MySQL errors that cause implicit ROLLBACK)
mysql_query('COMMIT');

使用最佳隔离级别的事务

我更喜欢"可重复读"(你不能看到其他人的数据,反之,直到你提交的事务)总是好的,这是默认的innodb存储引擎

如果您不使用innodb,请使用

更改隔离级别。

SET GLOBAL tx_isolation=' repeat - read ';或者

SET SESSION tx_isolation=' repeat - read ';

其余细节由@Buttle Butkus给出

设置tbl_groups和tbl_users的关系为ON DELETE CASCADE。然后只需更新tbl_groups,更改将级联到tbl_users中的相关记录。如果你需要经常这样更新父键那么你可以考虑使用代理键

下面的例子是基于面向对象的风格,确保你需要的数据库表类型是InnoDB,因为它支持事务语句

这里我只想删除基于id的多条记录

$this->link_id->autocommit(FALSE); 

//上面的语句通过禁用自动提交来启动事务,其中link_id指的是你的MySQLi数据库连接

        for($i=1; $i<=5; $i++){     
            $tSql = "DELETE FROM your_table" 
                     . " WHERE id=" . $i;
            $rs = $this->link_id->query($tSql);// execute the query
            if($this->link_id->affected_rows == -1) // check if it fails
            {   
               $_SESSION["error"] = "Sorry ! cant be deleted ! ";           
                $this->link_id->rollback(); // rollback the transaction
                break; // break the loop
            }           
        }

//check if there is some error or not, if no error then commit the transaction
        if(empty($_SESSION["error"])){          
            $this->link_id->commit();
        }