如果我在链上有多个查询,在基于 IF 的结构上,如下所示:
$query1 = mysqli_query("query here");
if(!query1){
//display error
} else {
$query2 = mysqli_query("another query here");
if(!query2){
//display error
//rollback the query1
} else {
query3 = mysqli_query("yet again another query");
if(!query3) {
//display error
//rollback the query2
//rollback the query1
} else {
query4 = mysqli_query("eh.. another one");
if(!query4){
//display error
//rollback the query3
//rollback the query2
//rollback the query1
} else {
return success;
}
}
}
}
如果下一个查询失败,是否有回滚上一个查询的最佳方法? 否则我将成功完成前 2 个查询,它编辑了数据库,但是 3° 失败了,所以 3° 和 4° 没有编辑数据库,结果是它被破坏了。
我想过类似的事情:
...
$query2 = mysqli_query("another query here");
if(!query2){
//display error
$rollback = mysqli_query("query to rollback query1");
} else {
query3 = mysqli_query("yet again another query");
if(!query3) {
//display error
$rollback = mysqli_query("query to rollback query2");
$rollback = mysqli_query("query to rollback query1");
} else {
...
但是上面的方法允许更多的机会使更多的查询失败。 还有其他更有效的方法吗?
最佳答案
这就是我用 mysqli
做的:
配置 mysqli(在应用程序开始的某个地方)在查询失败时抛出异常。
mysqli_report(MYSQLI_REPORT_STRICT);
这样你就不需要所有的if .. elseif .. else
。
$connection->begin_transaction();
try {
$result1 = $connection->query("query 1");
// do something with $result1
$result2 = $connection->query("query 2");
// do something with $result2
$result3 = $connection->query("query 3");
// do something with $result3
// you will not get here if any of the queries fails
$connection->commit();
} catch (Exception $e) {
// if any of the queries fails, the following code will be executed
$connection->rollback(); // roll back everything to the point of begin_transaction()
// do other stuff to handle the error
}
更新
通常用户不关心他的操作为什么失败。如果查询失败,那绝不是用户的错。这要么是开发者的错,要么是环境的错。因此,不应该根据哪个查询失败来呈现错误消息。
请注意,如果用户输入是失败查询的来源,则
- 您没有正确验证输入
- 您的查询不是 injection安全(如果输入可能导致 SQL 错误,它也可以用来破坏您的数据库。)
但是 - 我并不是说没有原因 - 我只是不知道。因此,如果您希望错误消息取决于哪个查询失败,您可以执行以下操作:
$error = null;
$connection->begin_transaction();
try {
try {
$result1 = $connection->query("query 1");
} catch (Exception $e) {
$error = 'query 1 failed';
throw $e;
}
// do something with $result1
try {
$result2 = $connection->query("query 2");
} catch (Exception $e) {
$error = 'query 2 failed';
throw $e;
}
// do something with $result2
// execute more queries the same way
$connection->commit();
} catch (Exception $e) {
$connection->rollback();
// use $error to find out which query failed
// do other stuff to handle the error
}
关于php - 回滚 MySQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42724708/